'use client'

import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useRouter } from 'next/navigation'
import { authFetch, clearToken, getApiBase, getToken, getEventStreamToken } from '../lib/auth'
import AdminShell from '../ui/AdminShell'
import AdminDiagnosticsPanel from '../ui/AdminDiagnosticsPanel'

type AdminSetting = {
  key: string
  value: string | null
  isSet: boolean
  source: string
  sensitive: boolean
}

type ServiceOptions = {
  rootFolders: { id: number; path: string; label: string }[]
  qualityProfiles: { id: number; name: string; label: string }[]
}

const SECTION_LABELS: Record<string, string> = {
  magent: 'Magent',
  general: 'General',
  notifications: 'Notifications',
  seerr: 'Seerr',
  jellyseerr: 'Seerr',
  jellyfin: 'Jellyfin',
  artwork: 'Artwork cache',
  cache: 'Cache Control',
  sonarr: 'Sonarr',
  radarr: 'Radarr',
  prowlarr: 'Prowlarr',
  qbittorrent: 'qBittorrent',
  log: 'Activity log',
  requests: 'Request sync',
  site: 'Site',
}

const BOOL_SETTINGS = new Set([
  'jellyfin_sync_to_arr',
  'site_banner_enabled',
  'magent_proxy_enabled',
  'magent_proxy_trust_forwarded_headers',
  'magent_ssl_bind_enabled',
  'magent_notify_enabled',
  'magent_notify_email_enabled',
  'magent_notify_email_use_tls',
  'magent_notify_email_use_ssl',
  'magent_notify_discord_enabled',
  'magent_notify_telegram_enabled',
  'magent_notify_push_enabled',
  'magent_notify_webhook_enabled',
])
const TEXTAREA_SETTINGS = new Set([
  'site_banner_message',
  'site_changelog',
  'magent_ssl_certificate_pem',
  'magent_ssl_private_key_pem',
])
const URL_SETTINGS = new Set([
  'magent_application_url',
  'magent_api_url',
  'magent_proxy_base_url',
  'magent_notify_discord_webhook_url',
  'magent_notify_push_base_url',
  'magent_notify_webhook_url',
  'jellyseerr_base_url',
  'jellyfin_base_url',
  'jellyfin_public_url',
  'sonarr_base_url',
  'radarr_base_url',
  'prowlarr_base_url',
  'qbittorrent_base_url',
])
const NUMBER_SETTINGS = new Set([
  'magent_application_port',
  'magent_api_port',
  'magent_notify_email_smtp_port',
  'log_file_max_bytes',
  'log_file_backup_count',
  'requests_sync_ttl_minutes',
  'requests_poll_interval_seconds',
  'requests_delta_sync_interval_minutes',
  'requests_cleanup_days',
])
const BANNER_TONES = ['info', 'warning', 'error', 'maintenance']

const SECTION_DESCRIPTIONS: Record<string, string> = {
  magent:
    'Magent service settings. Runtime and notification controls are organized under General and Notifications.',
  general:
    'Application runtime, binding, reverse proxy, and manual SSL settings for the Magent UI/API.',
  notifications:
    'Notification providers and delivery channel settings used by Magent messaging features.',
  seerr: 'Connect Seerr where users submit content requests.',
  jellyseerr: 'Connect Seerr where users submit content requests.',
  jellyfin: 'Control Jellyfin login and availability checks.',
  artwork: 'Cache posters/backdrops and review artwork coverage.',
  cache: 'Manage saved requests cache and refresh behavior.',
  sonarr: 'TV automation settings.',
  radarr: 'Movie automation settings.',
  prowlarr: 'Indexer search settings.',
  qbittorrent: 'Downloader connection settings.',
  requests: 'Control how often requests are refreshed and cleaned up.',
  log: 'Activity log for troubleshooting.',
  site: 'Sitewide banner, version, and changelog details.',
}

const SETTINGS_SECTION_MAP: Record<string, string | null> = {
  magent: 'magent',
  general: 'magent',
  notifications: 'magent',
  seerr: 'jellyseerr',
  jellyseerr: 'jellyseerr',
  jellyfin: 'jellyfin',
  artwork: null,
  sonarr: 'sonarr',
  radarr: 'radarr',
  prowlarr: 'prowlarr',
  qbittorrent: 'qbittorrent',
  requests: 'requests',
  cache: null,
  logs: 'log',
  maintenance: null,
  site: 'site',
}

const MAGENT_SECTION_GROUPS: Array<{
  key: string
  title: string
  description: string
  keys: string[]
}> = [
  {
    key: 'magent-runtime',
    title: 'Application',
    description:
      'Canonical application/API URLs and port defaults for the Magent UI/API endpoints.',
    keys: [
      'magent_application_url',
      'magent_application_port',
      'magent_api_url',
      'magent_api_port',
      'magent_bind_host',
    ],
  },
  {
    key: 'magent-proxy',
    title: 'Proxy',
    description:
      'Reverse proxy awareness and base URL handling when Magent sits behind Caddy/NGINX/Traefik.',
    keys: [
      'magent_proxy_enabled',
      'magent_proxy_base_url',
      'magent_proxy_trust_forwarded_headers',
      'magent_proxy_forwarded_prefix',
    ],
  },
  {
    key: 'magent-ssl',
    title: 'Manual SSL Bind',
    description:
      'Optional direct TLS binding values. Paste PEM certificate and private key or provide file paths.',
    keys: [
      'magent_ssl_bind_enabled',
      'magent_ssl_certificate_path',
      'magent_ssl_private_key_path',
      'magent_ssl_certificate_pem',
      'magent_ssl_private_key_pem',
    ],
  },
  {
    key: 'magent-notify-core',
    title: 'Notifications',
    description:
      'Global notification controls and provider-independent defaults used by Magent messaging features.',
    keys: ['magent_notify_enabled'],
  },
  {
    key: 'magent-notify-email',
    title: 'Email',
    description: 'SMTP configuration for email notifications.',
    keys: [
      'magent_notify_email_enabled',
      'magent_notify_email_smtp_host',
      'magent_notify_email_smtp_port',
      'magent_notify_email_smtp_username',
      'magent_notify_email_smtp_password',
      'magent_notify_email_from_address',
      'magent_notify_email_from_name',
      'magent_notify_email_use_tls',
      'magent_notify_email_use_ssl',
    ],
  },
  {
    key: 'magent-notify-discord',
    title: 'Discord',
    description: 'Webhook settings for Discord notifications and feedback routing.',
    keys: ['magent_notify_discord_enabled', 'magent_notify_discord_webhook_url'],
  },
  {
    key: 'magent-notify-telegram',
    title: 'Telegram',
    description: 'Bot token and chat target for Telegram notifications.',
    keys: [
      'magent_notify_telegram_enabled',
      'magent_notify_telegram_bot_token',
      'magent_notify_telegram_chat_id',
    ],
  },
  {
    key: 'magent-notify-push',
    title: 'Push / Mobile',
    description:
      'Generic push messaging configuration (ntfy, Gotify, Pushover, webhook-style push endpoints).',
    keys: [
      'magent_notify_push_enabled',
      'magent_notify_push_provider',
      'magent_notify_push_base_url',
      'magent_notify_push_topic',
      'magent_notify_push_token',
      'magent_notify_push_user_key',
      'magent_notify_push_device',
      'magent_notify_webhook_enabled',
      'magent_notify_webhook_url',
    ],
  },
]

const MAGENT_GROUPS_BY_SECTION: Record<string, Set<string>> = {
  general: new Set(['magent-runtime', 'magent-proxy', 'magent-ssl']),
  notifications: new Set([
    'magent-notify-core',
    'magent-notify-email',
    'magent-notify-discord',
    'magent-notify-telegram',
    'magent-notify-push',
  ]),
}

const SETTING_LABEL_OVERRIDES: Record<string, string> = {
  jellyseerr_base_url: 'Seerr base URL',
  jellyseerr_api_key: 'Seerr API key',
  magent_application_url: 'Application URL',
  magent_application_port: 'Application port',
  magent_api_url: 'API URL',
  magent_api_port: 'API port',
  magent_bind_host: 'Bind host',
  magent_proxy_enabled: 'Proxy support enabled',
  magent_proxy_base_url: 'Proxy base URL',
  magent_proxy_trust_forwarded_headers: 'Trust forwarded headers',
  magent_proxy_forwarded_prefix: 'Forwarded path prefix',
  magent_ssl_bind_enabled: 'Manual SSL bind enabled',
  magent_ssl_certificate_path: 'Certificate path',
  magent_ssl_private_key_path: 'Private key path',
  magent_ssl_certificate_pem: 'Certificate (PEM)',
  magent_ssl_private_key_pem: 'Private key (PEM)',
  magent_notify_enabled: 'Notifications enabled',
  magent_notify_email_enabled: 'Email notifications enabled',
  magent_notify_email_smtp_host: 'SMTP host',
  magent_notify_email_smtp_port: 'SMTP port',
  magent_notify_email_smtp_username: 'SMTP username',
  magent_notify_email_smtp_password: 'SMTP password',
  magent_notify_email_from_address: 'From email address',
  magent_notify_email_from_name: 'From display name',
  magent_notify_email_use_tls: 'Use STARTTLS',
  magent_notify_email_use_ssl: 'Use SSL/TLS (implicit)',
  magent_notify_discord_enabled: 'Discord notifications enabled',
  magent_notify_discord_webhook_url: 'Discord webhook URL',
  magent_notify_telegram_enabled: 'Telegram notifications enabled',
  magent_notify_telegram_bot_token: 'Telegram bot token',
  magent_notify_telegram_chat_id: 'Telegram chat ID',
  magent_notify_push_enabled: 'Push notifications enabled',
  magent_notify_push_provider: 'Push provider',
  magent_notify_push_base_url: 'Push provider/base URL',
  magent_notify_push_topic: 'Topic / channel',
  magent_notify_push_token: 'API token / password',
  magent_notify_push_user_key: 'User key / recipient key',
  magent_notify_push_device: 'Device / target',
  magent_notify_webhook_enabled: 'Generic webhook notifications enabled',
  magent_notify_webhook_url: 'Generic webhook URL',
  log_file_max_bytes: 'Log file max size (bytes)',
  log_file_backup_count: 'Rotated log files to keep',
  log_http_client_level: 'Service HTTP log level',
  log_background_sync_level: 'Background sync log level',
}

const labelFromKey = (key: string) =>
  SETTING_LABEL_OVERRIDES[key] ??
  key
    .replaceAll('_', ' ')
    .replace('jellyseerr', 'Seerr')
    .replace('base url', 'URL')
    .replace('api key', 'API key')
    .replace('quality profile id', 'Quality profile ID')
    .replace('root folder', 'Root folder')
    .replace('qbittorrent', 'qBittorrent')
    .replace('requests sync ttl minutes', 'Saved request refresh TTL (minutes)')
    .replace('requests poll interval seconds', 'Full refresh check interval (seconds)')
    .replace('requests delta sync interval minutes', 'Delta sync interval (minutes)')
    .replace('requests full sync time', 'Daily full refresh time (24h)')
    .replace('requests cleanup time', 'Daily history cleanup time (24h)')
    .replace('requests cleanup days', 'History retention window (days)')
    .replace('requests data source', 'Request source (cache vs Seerr)')
    .replace('jellyfin public url', 'Jellyfin public URL')
    .replace('jellyfin sync to arr', 'Sync Jellyfin to Sonarr/Radarr')
    .replace('artwork cache mode', 'Artwork cache mode')
    .replace('site build number', 'Build number')
    .replace('site banner enabled', 'Sitewide banner enabled')
    .replace('site banner message', 'Sitewide banner message')
    .replace('site banner tone', 'Sitewide banner tone')
    .replace('site changelog', 'Changelog text')

const formatBytes = (value?: number | null) => {
  if (!value || value <= 0) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  let size = value
  let unitIndex = 0
  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex += 1
  }
  const decimals = unitIndex === 0 || size >= 10 ? 0 : 1
  return `${size.toFixed(decimals)} ${units[unitIndex]}`
}

type SettingsPageProps = {
  section: string
}

type SettingsSectionGroup = {
  key: string
  title: string
  items: AdminSetting[]
  description?: string
}

type SectionFeedback = {
  tone: 'status' | 'error'
  message: string
}

const SERVICE_TEST_ENDPOINTS: Record<string, string> = {
  jellyseerr: 'seerr',
  jellyfin: 'jellyfin',
  sonarr: 'sonarr',
  radarr: 'radarr',
  prowlarr: 'prowlarr',
  qbittorrent: 'qbittorrent',
}

export default function SettingsPage({ section }: SettingsPageProps) {
  const router = useRouter()
  const [settings, setSettings] = useState<AdminSetting[]>([])
  const [formValues, setFormValues] = useState<Record<string, string>>({})
  const [status, setStatus] = useState<string | null>(null)
  const [sectionFeedback, setSectionFeedback] = useState<Record<string, SectionFeedback>>({})
  const [sectionSaving, setSectionSaving] = useState<Record<string, boolean>>({})
  const [sectionTesting, setSectionTesting] = useState<Record<string, boolean>>({})
  const [emailTestRecipient, setEmailTestRecipient] = useState('')
  const [loading, setLoading] = useState(true)
  const [sonarrOptions, setSonarrOptions] = useState<ServiceOptions | null>(null)
  const [radarrOptions, setRadarrOptions] = useState<ServiceOptions | null>(null)
  const [sonarrError, setSonarrError] = useState<string | null>(null)
  const [radarrError, setRadarrError] = useState<string | null>(null)
  const [jellyfinSyncStatus, setJellyfinSyncStatus] = useState<string | null>(null)
  const [requestsSyncStatus, setRequestsSyncStatus] = useState<string | null>(null)
  const [artworkPrefetchStatus, setArtworkPrefetchStatus] = useState<string | null>(null)
  const [logsStatus, setLogsStatus] = useState<string | null>(null)
  const [logsLines, setLogsLines] = useState<string[]>([])
  const [logsCount, setLogsCount] = useState(200)
  const [cacheRows, setCacheRows] = useState<any[]>([])
  const [cacheCount, setCacheCount] = useState(50)
  const [cacheStatus, setCacheStatus] = useState<string | null>(null)
  const [cacheLoading, setCacheLoading] = useState(false)
  const [requestsSync, setRequestsSync] = useState<any | null>(null)
  const [artworkPrefetch, setArtworkPrefetch] = useState<any | null>(null)
  const [artworkSummary, setArtworkSummary] = useState<any | null>(null)
  const [artworkSummaryStatus, setArtworkSummaryStatus] = useState<string | null>(null)
  const [maintenanceStatus, setMaintenanceStatus] = useState<string | null>(null)
  const [maintenanceBusy, setMaintenanceBusy] = useState(false)
  const [liveStreamConnected, setLiveStreamConnected] = useState(false)
  const requestsSyncRef = useRef<any | null>(null)
  const artworkPrefetchRef = useRef<any | null>(null)
  const computeProgressPercent = (
    completedValue: unknown,
    totalValue: unknown,
    statusValue: unknown
  ): number => {
    if (String(statusValue).toLowerCase() === 'completed') {
      return 100
    }
    const completed = Number(completedValue)
    const total = Number(totalValue)
    if (!Number.isFinite(completed) || !Number.isFinite(total) || total <= 0 || completed <= 0) {
      return 0
    }
    return Math.max(0, Math.min(100, Math.round((completed / total) * 100)))
  }

  const loadSettings = useCallback(async (refreshedKeys?: Set<string>) => {
    const baseUrl = getApiBase()
    const response = await authFetch(`${baseUrl}/admin/settings`)
    if (!response.ok) {
      if (response.status === 401) {
        clearToken()
        router.push('/login')
        return
      }
      if (response.status === 403) {
        router.push('/')
        return
      }
      throw new Error('Failed to load settings')
    }
    const data = await response.json()
    const fetched = Array.isArray(data?.settings) ? data.settings : []
    setSettings(fetched)
    const initialValues: Record<string, string> = {}
    for (const setting of fetched) {
      if (!setting.sensitive && setting.value) {
        if (BOOL_SETTINGS.has(setting.key)) {
          initialValues[setting.key] = String(setting.value).toLowerCase()
        } else {
          initialValues[setting.key] = setting.value
        }
      } else {
        initialValues[setting.key] = ''
      }
    }
    setFormValues((current) => {
      if (!refreshedKeys || refreshedKeys.size === 0) {
        return initialValues
      }
      const nextValues = { ...initialValues }
      for (const [key, value] of Object.entries(current)) {
        if (!refreshedKeys.has(key)) {
          nextValues[key] = value
        }
      }
      return nextValues
    })
    setStatus(null)
  }, [router])

  const loadArtworkPrefetchStatus = useCallback(async () => {
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/requests/artwork/status`)
      if (!response.ok) {
        return
      }
      const data = await response.json()
      setArtworkPrefetch(data?.prefetch ?? null)
    } catch (err) {
      console.error(err)
    }
  }, [])

  const loadArtworkSummary = useCallback(async () => {
    setArtworkSummaryStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/requests/artwork/summary`)
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Artwork summary fetch failed')
      }
      const data = await response.json()
      setArtworkSummary(data?.summary ?? null)
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not load artwork stats.'
      setArtworkSummaryStatus(message)
    }
  }, [])

  const loadOptions = useCallback(async (service: 'sonarr' | 'radarr') => {
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/${service}/options`)
      if (!response.ok) {
        throw new Error('Options unavailable')
      }
      const data = await response.json()
      if (service === 'sonarr') {
        setSonarrOptions({
          rootFolders: Array.isArray(data?.rootFolders) ? data.rootFolders : [],
          qualityProfiles: Array.isArray(data?.qualityProfiles) ? data.qualityProfiles : [],
        })
        setSonarrError(null)
      } else {
        setRadarrOptions({
          rootFolders: Array.isArray(data?.rootFolders) ? data.rootFolders : [],
          qualityProfiles: Array.isArray(data?.qualityProfiles) ? data.qualityProfiles : [],
        })
        setRadarrError(null)
      }
    } catch (err) {
      console.error(err)
      if (service === 'sonarr') {
        setSonarrError('Could not load Sonarr options.')
      } else {
        setRadarrError('Could not load Radarr options.')
      }
    }
  }, [])

  useEffect(() => {
    const load = async () => {
      if (!getToken()) {
        router.push('/login')
        return
      }
      try {
        await loadSettings()
        if (section === 'cache' || section === 'artwork') {
          await loadArtworkPrefetchStatus()
          await loadArtworkSummary()
        }
      } catch (err) {
        console.error(err)
        setStatus('Could not load admin settings.')
      } finally {
        setLoading(false)
      }
    }

    load()
    if (section === 'sonarr') {
      void loadOptions('sonarr')
    }
    if (section === 'radarr') {
      void loadOptions('radarr')
    }
  }, [loadArtworkPrefetchStatus, loadArtworkSummary, loadOptions, loadSettings, router, section])

  const groupedSettings = useMemo(() => {
    const groups: Record<string, AdminSetting[]> = {}
    for (const setting of settings) {
      const section = setting.key.split('_')[0] ?? 'other'
      if (!groups[section]) groups[section] = []
      groups[section].push(setting)
    }
    return groups
  }, [settings])

  const settingsSection = SETTINGS_SECTION_MAP[section] ?? null
  const isMagentGroupedSection = section === 'magent' || section === 'general' || section === 'notifications'
  const visibleSections = settingsSection ? [settingsSection] : []
  const isCacheSection = section === 'cache'
  const cacheSettingKeys = new Set(['requests_sync_ttl_minutes', 'requests_data_source'])
  const artworkSettingKeys = new Set(['artwork_cache_mode'])
  const hiddenSettingKeys = new Set([...cacheSettingKeys, ...artworkSettingKeys])
  const requestSettingOrder = [
    'requests_poll_interval_seconds',
    'requests_delta_sync_interval_minutes',
    'requests_full_sync_time',
    'requests_cleanup_time',
    'requests_cleanup_days',
  ]
  const sortByOrder = (items: AdminSetting[], order: string[]) => {
    const position = new Map(order.map((key, index) => [key, index]))
    return [...items].sort((a, b) => {
      const aIndex = position.get(a.key) ?? Number.POSITIVE_INFINITY
      const bIndex = position.get(b.key) ?? Number.POSITIVE_INFINITY
      if (aIndex !== bIndex) return aIndex - bIndex
      return a.key.localeCompare(b.key)
    })
  }
  const cacheSettings = settings.filter((setting) => cacheSettingKeys.has(setting.key))
  const artworkSettings = settings.filter((setting) => artworkSettingKeys.has(setting.key))
  const settingsSections: SettingsSectionGroup[] = isCacheSection
    ? [
        { key: 'cache', title: 'Cache control', items: cacheSettings },
        { key: 'artwork', title: 'Artwork cache', items: artworkSettings },
      ]
    : isMagentGroupedSection
      ? (() => {
          if (section === 'magent') {
            return []
          }
          const magentItems = groupedSettings.magent ?? []
          const byKey = new Map(magentItems.map((item) => [item.key, item]))
          const allowedGroupKeys = MAGENT_GROUPS_BY_SECTION[section] ?? new Set<string>()
          const groups: SettingsSectionGroup[] = MAGENT_SECTION_GROUPS.filter((group) =>
            allowedGroupKeys.has(group.key),
          ).map((group) => {
            const items = group.keys
              .map((key) => byKey.get(key))
              .filter((item): item is AdminSetting => Boolean(item))
            return {
              key: group.key,
              title: group.title,
              description: group.description,
              items,
            }
          })
          return groups
        })()
      : visibleSections.map((sectionKey) => ({
          key: sectionKey,
          title: SECTION_LABELS[sectionKey] ?? sectionKey,
          items: (() => {
            const sectionItems = groupedSettings[sectionKey] ?? []
            const filtered =
              sectionKey === 'requests' || sectionKey === 'artwork'
                ? sectionItems.filter((setting) => !hiddenSettingKeys.has(setting.key))
                : sectionItems
            if (sectionKey === 'requests') {
              return sortByOrder(filtered, requestSettingOrder)
            }
            return filtered
          })(),
        }))
  const showLogs = section === 'logs'
  const showMaintenance = section === 'maintenance'
  const showRequestsExtras = section === 'requests'
  const showArtworkExtras = section === 'cache'
  const showCacheExtras = section === 'cache'
  const shouldRenderSection = (sectionGroup: { key: string; items?: AdminSetting[] }) => {
    if (sectionGroup.items && sectionGroup.items.length > 0) return true
    if (showArtworkExtras && sectionGroup.key === 'artwork') return true
    if (showCacheExtras && sectionGroup.key === 'cache') return true
    if (showRequestsExtras && sectionGroup.key === 'requests') return true
    return false
  }

  useEffect(() => {
    requestsSyncRef.current = requestsSync
  }, [requestsSync])

  useEffect(() => {
    artworkPrefetchRef.current = artworkPrefetch
  }, [artworkPrefetch])

  const settingDescriptions: Record<string, string> = {
    magent_application_url:
      'Canonical public URL for the Magent web app (used for links and reverse-proxy-aware features).',
    magent_application_port:
      'Preferred frontend/UI port for local or direct-hosted deployments.',
    magent_api_url:
      'Canonical public URL for the Magent API when it differs from the app URL.',
    magent_api_port: 'Preferred API port for local or direct-hosted deployments.',
    magent_bind_host:
      'Host/IP to bind the application services to when running without an external process manager.',
    magent_proxy_enabled:
      'Enable reverse-proxy-aware behavior and use proxy-specific URL settings.',
    magent_proxy_base_url:
      'Base URL Magent should use when it is published behind a proxy path or external proxy hostname.',
    magent_proxy_trust_forwarded_headers:
      'Trust X-Forwarded-* headers from your reverse proxy.',
    magent_proxy_forwarded_prefix:
      'Optional path prefix added by your proxy (example: /magent).',
    magent_ssl_bind_enabled:
      'Enable direct HTTPS binding in Magent (for environments not terminating TLS at a proxy).',
    magent_ssl_certificate_path:
      'Path to the TLS certificate file on disk (PEM).',
    magent_ssl_private_key_path:
      'Path to the TLS private key file on disk (PEM).',
    magent_ssl_certificate_pem:
      'Paste the TLS certificate PEM if you want Magent to store it directly.',
    magent_ssl_private_key_pem:
      'Paste the TLS private key PEM if you want Magent to store it directly.',
    magent_notify_enabled:
      'Master switch for Magent notifications. Individual provider toggles still apply.',
    magent_notify_email_enabled: 'Enable SMTP email notifications.',
    magent_notify_email_smtp_host: 'SMTP server hostname or IP.',
    magent_notify_email_smtp_port: 'SMTP port (587 for STARTTLS, 465 for SSL).',
    magent_notify_email_smtp_username: 'SMTP account username.',
    magent_notify_email_smtp_password: 'SMTP account password or app password.',
    magent_notify_email_from_address: 'Sender email address used by Magent.',
    magent_notify_email_from_name: 'Sender display name shown to recipients.',
    magent_notify_email_use_tls: 'Use STARTTLS after connecting to SMTP.',
    magent_notify_email_use_ssl: 'Use implicit TLS/SSL for SMTP (usually port 465).',
    magent_notify_discord_enabled: 'Enable Discord webhook notifications.',
    magent_notify_discord_webhook_url:
      'Discord channel webhook URL used for notifications and optional feedback routing.',
    magent_notify_telegram_enabled: 'Enable Telegram notifications.',
    magent_notify_telegram_bot_token: 'Bot token from BotFather.',
    magent_notify_telegram_chat_id:
      'Default Telegram chat/group/user ID for notifications.',
    magent_notify_push_enabled: 'Enable generic push notifications.',
    magent_notify_push_provider:
      'Push backend to target (ntfy, gotify, pushover, webhook, etc.).',
    magent_notify_push_base_url:
      'Base URL for your push provider (for example ntfy/gotify server URL).',
    magent_notify_push_topic: 'Topic/channel/room name used by the push provider.',
    magent_notify_push_token: 'Provider token/API key/password.',
    magent_notify_push_user_key:
      'Provider recipient key/user key (for example Pushover user key).',
    magent_notify_push_device:
      'Optional device or target override, depending on provider.',
    magent_notify_webhook_enabled: 'Enable generic webhook notifications.',
    magent_notify_webhook_url:
      'Generic webhook endpoint for custom integrations or automation flows.',
    jellyseerr_base_url:
      'Base URL for your Seerr server (FQDN or IP). Scheme is optional.',
    jellyseerr_api_key: 'API key used to read requests and status.',
    jellyfin_base_url:
      'Jellyfin server URL for logins and lookups (FQDN or IP). Scheme is optional.',
    jellyfin_api_key: 'Admin API key for syncing users and availability.',
    jellyfin_public_url:
      'Public Jellyfin URL for the “Open in Jellyfin” button (FQDN or IP).',
    jellyfin_sync_to_arr: 'Auto-add items to Sonarr/Radarr when they already exist in Jellyfin.',
    artwork_cache_mode: 'Choose whether posters are cached locally or loaded from the web.',
    sonarr_base_url: 'Sonarr server URL for TV tracking (FQDN or IP). Scheme is optional.',
    sonarr_api_key: 'API key for Sonarr.',
    sonarr_quality_profile_id: 'Quality profile used when adding TV shows.',
    sonarr_root_folder: 'Root folder where Sonarr stores TV shows.',
    sonarr_qbittorrent_category: 'qBittorrent category for manual Sonarr downloads.',
    radarr_base_url: 'Radarr server URL for movies (FQDN or IP). Scheme is optional.',
    radarr_api_key: 'API key for Radarr.',
    radarr_quality_profile_id: 'Quality profile used when adding movies.',
    radarr_root_folder: 'Root folder where Radarr stores movies.',
    radarr_qbittorrent_category: 'qBittorrent category for manual Radarr downloads.',
    prowlarr_base_url:
      'Prowlarr server URL for indexer searches (FQDN or IP). Scheme is optional.',
    prowlarr_api_key: 'API key for Prowlarr.',
    qbittorrent_base_url:
      'qBittorrent server URL for download status (FQDN or IP). Scheme is optional.',
    qbittorrent_username: 'qBittorrent login username.',
    qbittorrent_password: 'qBittorrent login password.',
    requests_sync_ttl_minutes: 'How long saved requests stay fresh before a refresh is needed.',
    requests_poll_interval_seconds:
      'How often Magent checks if a full refresh should run.',
    requests_delta_sync_interval_minutes:
      'How often we poll for new or updated requests.',
    requests_full_sync_time: 'Daily time to rebuild the full request cache.',
    requests_cleanup_time: 'Daily time to trim old request history.',
    requests_cleanup_days: 'History older than this is removed during cleanup.',
    requests_data_source:
      'Pick where Magent should read requests from. Cache-only avoids Seerr lookups on reads.',
    log_level: 'How much detail is written to the activity log.',
    log_file: 'Where the activity log is stored.',
    log_file_max_bytes: 'Rotate the log file when it reaches this size in bytes.',
    log_file_backup_count: 'How many rotated log files to retain on disk.',
    log_http_client_level:
      'Verbosity for per-call outbound service traffic logs from Seerr, Jellyfin, Sonarr, Radarr, and related clients.',
    log_background_sync_level:
      'Verbosity for scheduled background sync progress messages.',
    site_build_number: 'Build number shown in the account menu (auto-set from releases).',
    site_banner_enabled: 'Enable a sitewide banner for announcements.',
    site_banner_message: 'Short banner message for maintenance or updates.',
    site_banner_tone: 'Visual tone for the banner.',
    site_changelog: 'One update per line for the public changelog.',
  }

  const settingPlaceholders: Record<string, string> = {
    magent_application_url: 'https://magent.example.com',
    magent_application_port: '3000',
    magent_api_url: 'https://api.example.com or https://magent.example.com/api',
    magent_api_port: '8000',
    magent_bind_host: '0.0.0.0',
    magent_proxy_base_url: 'https://proxy.example.com/magent',
    magent_proxy_forwarded_prefix: '/magent',
    magent_ssl_certificate_path: '/certs/fullchain.pem',
    magent_ssl_private_key_path: '/certs/privkey.pem',
    magent_ssl_certificate_pem: '-----BEGIN CERTIFICATE-----',
    magent_ssl_private_key_pem: '-----BEGIN PRIVATE KEY-----',
    magent_notify_email_smtp_host: 'smtp.office365.com',
    magent_notify_email_smtp_port: '587',
    magent_notify_email_smtp_username: 'notifications@example.com',
    magent_notify_email_from_address: 'notifications@example.com',
    magent_notify_email_from_name: 'Magent',
    log_file_max_bytes: '20000000',
    log_file_backup_count: '10',
    magent_notify_discord_webhook_url: 'https://discord.com/api/webhooks/...',
    magent_notify_telegram_bot_token: '123456789:AA...',
    magent_notify_telegram_chat_id: '-1001234567890',
    magent_notify_push_base_url: 'https://ntfy.example.com or https://gotify.example.com',
    magent_notify_push_topic: 'magent-alerts',
    magent_notify_push_device: 'iphone-zak',
    magent_notify_webhook_url: 'https://automation.example.com/webhooks/magent',
    jellyseerr_base_url: 'https://requests.example.com or 10.30.1.81:5055',
    jellyfin_base_url: 'https://jelly.example.com or 10.40.0.80:8096',
    jellyfin_public_url: 'https://jelly.example.com',
    sonarr_base_url: 'https://sonarr.example.com or 10.30.1.81:8989',
    radarr_base_url: 'https://radarr.example.com or 10.30.1.81:7878',
    prowlarr_base_url: 'https://prowlarr.example.com or 10.30.1.81:9696',
    qbittorrent_base_url: 'https://qb.example.com or 10.30.1.81:8080',
  }

  const buildSelectOptions = (
    currentValue: string,
    options: { id: number; label: string; path?: string }[],
    includePath: boolean
  ) => {
    const optionValues = new Set(options.map((option) => String(option.id)))
    const list = options.map((option) => (
      <option key={option.id} value={String(option.id)}>
        {includePath && option.path ? option.path : option.label}
      </option>
    ))
    if (currentValue && !optionValues.has(currentValue)) {
      list.unshift(
        <option key="custom" value={currentValue}>
          Custom: {currentValue}
        </option>
      )
    }
    return list
  }

  const parseActionError = (err: unknown, fallback: string) => {
    if (err instanceof Error && err.message) {
      return err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
    }
    return fallback
  }

  const buildSettingsPayload = (items: AdminSetting[]) => {
    const payload: Record<string, string> = {}
    for (const setting of items) {
      const rawValue = formValues[setting.key]
      if (typeof rawValue !== 'string') {
        continue
      }
      const value = rawValue.trim()
      if (setting.sensitive && value === '') {
        continue
      }
      payload[setting.key] = value
    }
    return payload
  }

  const saveSettingGroup = async (
    sectionGroup: SettingsSectionGroup,
    options?: { successMessage?: string | null },
  ) => {
    setSectionFeedback((current) => {
      const next = { ...current }
      delete next[sectionGroup.key]
      return next
    })
    setSectionSaving((current) => ({ ...current, [sectionGroup.key]: true }))
    try {
      const payload = buildSettingsPayload(sectionGroup.items)
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/settings`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Update failed')
      }
      await loadSettings(new Set(sectionGroup.items.map((item) => item.key)))
      if (options?.successMessage !== null) {
        setSectionFeedback((current) => ({
          ...current,
          [sectionGroup.key]: {
            tone: 'status',
            message: options?.successMessage ?? `${sectionGroup.title} settings saved.`,
          },
        }))
      }
      return true
    } catch (err) {
      console.error(err)
      setSectionFeedback((current) => ({
        ...current,
        [sectionGroup.key]: {
          tone: 'error',
          message: parseActionError(err, 'Could not save settings.'),
        },
      }))
      return false
    } finally {
      setSectionSaving((current) => ({ ...current, [sectionGroup.key]: false }))
    }
  }

  const formatServiceTestFeedback = (result: any): SectionFeedback => {
    const name = result?.name ?? 'Service'
    const state = String(result?.status ?? 'unknown').toLowerCase()
    if (state === 'up') {
      return { tone: 'status', message: `${name} connection test passed.` }
    }
    if (state === 'degraded') {
      return {
        tone: 'error',
        message: result?.message ? `${name}: ${result.message}` : `${name} reported warnings.`,
      }
    }
    if (state === 'not_configured') {
      return { tone: 'error', message: `${name} is not fully configured yet.` }
    }
    return {
      tone: 'error',
      message: result?.message ? `${name}: ${result.message}` : `${name} connection test failed.`,
    }
  }

  const getSectionTestLabel = (sectionKey: string) => {
    if (sectionKey === 'magent-notify-email') {
      return 'Send test email'
    }
    if (sectionKey in SERVICE_TEST_ENDPOINTS) {
      return 'Test connection'
    }
    return null
  }

  const testSettingGroup = async (sectionGroup: SettingsSectionGroup) => {
    setSectionFeedback((current) => {
      const next = { ...current }
      delete next[sectionGroup.key]
      return next
    })
    setSectionTesting((current) => ({ ...current, [sectionGroup.key]: true }))
    try {
      const saved = await saveSettingGroup(sectionGroup, { successMessage: null })
      if (!saved) {
        return
      }

      const baseUrl = getApiBase()
      if (sectionGroup.key === 'magent-notify-email') {
        const recipientEmail =
          emailTestRecipient.trim() || formValues.magent_notify_email_from_address?.trim()
        const response = await authFetch(`${baseUrl}/admin/settings/test/email`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(
            recipientEmail ? { recipient_email: recipientEmail } : {},
          ),
        })
        if (!response.ok) {
          const text = await response.text()
          throw new Error(text || 'Email test failed')
        }
        const data = await response.json()
        setSectionFeedback((current) => ({
          ...current,
          [sectionGroup.key]: {
            tone: 'status',
            message: `Test email sent to ${data?.recipient_email ?? 'the configured mailbox'}.`,
          },
        }))
        return
      }

      const serviceKey = SERVICE_TEST_ENDPOINTS[sectionGroup.key]
      if (!serviceKey) {
        return
      }
      const response = await authFetch(`${baseUrl}/status/services/${serviceKey}/test`, {
        method: 'POST',
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Connection test failed')
      }
      const data = await response.json()
      setSectionFeedback((current) => ({
        ...current,
        [sectionGroup.key]: formatServiceTestFeedback(data),
      }))
    } catch (err) {
      console.error(err)
      setSectionFeedback((current) => ({
        ...current,
        [sectionGroup.key]: {
          tone: 'error',
          message: parseActionError(err, 'Could not run test.'),
        },
      }))
    } finally {
      setSectionTesting((current) => ({ ...current, [sectionGroup.key]: false }))
    }
  }

  const syncJellyfinUsers = async () => {
    setJellyfinSyncStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/jellyfin/users/sync`, {
        method: 'POST',
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Sync failed')
      }
      const data = await response.json()
      setJellyfinSyncStatus(`Imported ${data?.imported ?? 0} users from Jellyfin.`)
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not import Jellyfin users.'
      setJellyfinSyncStatus(message)
    }
  }

  const syncRequests = async () => {
    setRequestsSyncStatus(null)
    setRequestsSync({
      status: 'running',
      stored: 0,
      total: 0,
      skip: 0,
      message: 'Starting sync',
    })
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/requests/sync`, {
        method: 'POST',
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Sync failed')
      }
      const data = await response.json()
      setRequestsSync(data?.sync ?? null)
      setRequestsSyncStatus('Sync started.')
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not sync requests.'
      setRequestsSyncStatus(message)
    }
  }

  const syncRequestsDelta = async () => {
    setRequestsSyncStatus(null)
    setRequestsSync({
      status: 'running',
      stored: 0,
      total: 0,
      skip: 0,
      message: 'Starting delta sync',
    })
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/requests/sync/delta`, {
        method: 'POST',
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Delta sync failed')
      }
      const data = await response.json()
      setRequestsSync(data?.sync ?? null)
      setRequestsSyncStatus('Delta sync started.')
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not run delta sync.'
      setRequestsSyncStatus(message)
    }
  }

  const prefetchArtwork = async () => {
    setArtworkPrefetchStatus(null)
    setArtworkPrefetch({
      status: 'running',
      processed: 0,
      total: 0,
      message: 'Starting artwork caching',
    })
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/requests/artwork/prefetch`, {
        method: 'POST',
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Artwork prefetch failed')
      }
      const data = await response.json()
      setArtworkPrefetch(data?.prefetch ?? null)
      setArtworkPrefetchStatus('Artwork caching started.')
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not cache artwork.'
      setArtworkPrefetchStatus(message)
    }
  }

  const prefetchArtworkMissing = async () => {
    setArtworkPrefetchStatus(null)
    setArtworkPrefetch({
      status: 'running',
      processed: 0,
      total: 0,
      message: 'Starting missing artwork caching',
    })
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(
        `${baseUrl}/admin/requests/artwork/prefetch?only_missing=1`,
        { method: 'POST' }
      )
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Missing artwork prefetch failed')
      }
      const data = await response.json()
      setArtworkPrefetch(data?.prefetch ?? null)
      setArtworkPrefetchStatus('Missing artwork caching started.')
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not cache missing artwork.'
      setArtworkPrefetchStatus(message)
    }
  }

  useEffect(() => {
    const shouldSubscribe = showRequestsExtras || showArtworkExtras || showLogs
    if (!shouldSubscribe) {
      setLiveStreamConnected(false)
      return
    }
    const token = getToken()
    if (!token) {
      setLiveStreamConnected(false)
      return
    }

    const baseUrl = getApiBase()
    let closed = false
    let source: EventSource | null = null

    const connect = async () => {
      try {
        const streamToken = await getEventStreamToken()
        if (closed) return
        const params = new URLSearchParams()
        params.set('stream_token', streamToken)
        if (showLogs) {
          params.set('include_logs', '1')
          params.set('log_lines', String(logsCount))
        }
        const streamUrl = `${baseUrl}/admin/events/stream?${params.toString()}`
        source = new EventSource(streamUrl)

        source.onopen = () => {
          if (closed) return
          setLiveStreamConnected(true)
        }

        source.onmessage = (event) => {
          if (closed) return
          setLiveStreamConnected(true)
          try {
            const payload = JSON.parse(event.data)
            if (!payload || payload.type !== 'admin_live_state') {
              return
            }

            const rawSync =
              payload.requestsSync && typeof payload.requestsSync === 'object'
                ? payload.requestsSync
                : null
            const nextSync = rawSync?.status === 'idle' ? null : rawSync
            const prevSync = requestsSyncRef.current
            requestsSyncRef.current = nextSync
            setRequestsSync(nextSync)
            if (
              prevSync?.status === 'running' &&
              nextSync?.status &&
              nextSync.status !== 'running'
            ) {
              setRequestsSyncStatus(nextSync.message || 'Sync complete.')
            }

            const rawArtwork =
              payload.artworkPrefetch && typeof payload.artworkPrefetch === 'object'
                ? payload.artworkPrefetch
                : null
            const nextArtwork = rawArtwork?.status === 'idle' ? null : rawArtwork
            const prevArtwork = artworkPrefetchRef.current
            artworkPrefetchRef.current = nextArtwork
            setArtworkPrefetch(nextArtwork)
            if (
              prevArtwork?.status === 'running' &&
              nextArtwork?.status &&
              nextArtwork.status !== 'running'
            ) {
              setArtworkPrefetchStatus(nextArtwork.message || 'Artwork caching complete.')
              if (showArtworkExtras) {
                void loadArtworkSummary()
              }
            }

            if (payload.logs && typeof payload.logs === 'object') {
              if (Array.isArray(payload.logs.lines)) {
                setLogsLines(payload.logs.lines)
                setLogsStatus(null)
              } else if (typeof payload.logs.error === 'string' && payload.logs.error.trim()) {
                setLogsStatus(payload.logs.error)
              }
            }
          } catch (err) {
            console.error(err)
          }
        }

        source.onerror = () => {
          if (closed) return
          setLiveStreamConnected(false)
        }
      } catch (err) {
        if (closed) return
        console.error(err)
        setLiveStreamConnected(false)
      }
    }

    void connect()

    return () => {
      closed = true
      setLiveStreamConnected(false)
      source?.close()
    }
  }, [loadArtworkSummary, logsCount, showArtworkExtras, showLogs, showRequestsExtras])

  useEffect(() => {
    if (liveStreamConnected || !artworkPrefetch || artworkPrefetch.status !== 'running') {
      return
    }
    let active = true
    const timer = setInterval(async () => {
      try {
        const baseUrl = getApiBase()
        const response = await authFetch(`${baseUrl}/admin/requests/artwork/status`)
        if (!response.ok) {
          return
        }
        const data = await response.json()
        if (!active) return
        setArtworkPrefetch(data?.prefetch ?? null)
        if (data?.prefetch?.status && data.prefetch.status !== 'running') {
          setArtworkPrefetchStatus(data.prefetch.message || 'Artwork caching complete.')
          void loadArtworkSummary()
        }
      } catch (err) {
        console.error(err)
      }
    }, 2000)
    return () => {
      active = false
      clearInterval(timer)
    }
  }, [artworkPrefetch, liveStreamConnected, loadArtworkSummary])

  useEffect(() => {
    if (!artworkPrefetch || artworkPrefetch.status === 'running') {
      return
    }
    const timer = setTimeout(() => {
      setArtworkPrefetch(null)
    }, 5000)
    return () => clearTimeout(timer)
  }, [artworkPrefetch])

  useEffect(() => {
    if (liveStreamConnected || !requestsSync || requestsSync.status !== 'running') {
      return
    }
    let active = true
    const timer = setInterval(async () => {
      try {
        const baseUrl = getApiBase()
        const response = await authFetch(`${baseUrl}/admin/requests/sync/status`)
        if (!response.ok) {
          return
        }
        const data = await response.json()
        if (!active) return
        setRequestsSync(data?.sync ?? null)
        if (data?.sync?.status && data.sync.status !== 'running') {
          setRequestsSyncStatus(data.sync.message || 'Sync complete.')
        }
      } catch (err) {
        console.error(err)
      }
    }, 2000)
    return () => {
      active = false
      clearInterval(timer)
    }
  }, [liveStreamConnected, requestsSync])

  useEffect(() => {
    if (!requestsSync || requestsSync.status === 'running') {
      return
    }
    const timer = setTimeout(() => {
      setRequestsSync(null)
    }, 5000)
    return () => clearTimeout(timer)
  }, [requestsSync])

  const loadLogs = useCallback(async () => {
    setLogsStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(
        `${baseUrl}/admin/logs?lines=${encodeURIComponent(String(logsCount))}`
      )
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Log fetch failed')
      }
      const data = await response.json()
      if (Array.isArray(data?.lines)) {
        setLogsLines(data.lines)
      } else {
        setLogsLines([])
      }
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not load logs.'
      setLogsStatus(message)
    }
  }, [logsCount])

  useEffect(() => {
    if (!showLogs) {
      return
    }
    if (liveStreamConnected) {
      return
    }
    void loadLogs()
    const timer = setInterval(() => {
      void loadLogs()
    }, 5000)
    return () => clearInterval(timer)
  }, [liveStreamConnected, loadLogs, showLogs])

  const loadCache = async () => {
    setCacheStatus(null)
    setCacheLoading(true)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(
        `${baseUrl}/admin/requests/cache?limit=${encodeURIComponent(String(cacheCount))}`
      )
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Cache fetch failed')
      }
      const data = await response.json()
      if (Array.isArray(data?.rows)) {
        setCacheRows(data.rows)
      } else {
        setCacheRows([])
      }
    } catch (err) {
      console.error(err)
      const message =
        err instanceof Error && err.message
          ? err.message.replace(/^\\{\"detail\":\"|\"\\}$/g, '')
          : 'Could not load cache.'
      setCacheStatus(message)
    } finally {
      setCacheLoading(false)
    }
  }

  const runRepair = async () => {
    setMaintenanceStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/maintenance/repair`, { method: 'POST' })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Repair failed')
      }
      const data = await response.json()
      setMaintenanceStatus(`Integrity check: ${data?.integrity ?? 'unknown'}. Vacuum complete.`)
    } catch (err) {
      console.error(err)
      setMaintenanceStatus('Database repair failed.')
    }
  }

  const runCleanup = async () => {
    setMaintenanceStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/maintenance/cleanup?days=90`, {
        method: 'POST',
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Cleanup failed')
      }
      const data = await response.json()
      setMaintenanceStatus(
        `Cleaned history older than ${data?.days ?? 90} days.`
      )
    } catch (err) {
      console.error(err)
      setMaintenanceStatus('Cleanup failed.')
    }
  }

  const runFlushAndResync = async () => {
    setMaintenanceStatus(null)
    setMaintenanceBusy(true)
    if (typeof window !== 'undefined') {
      const ok = window.confirm(
        'This will perform a nuclear reset: clear cached requests/history, wipe non-admin users, invites, and profiles, then re-sync users and requests from Seerr. Continue?'
      )
      if (!ok) {
        setMaintenanceBusy(false)
        return
      }
    }
    try {
      const baseUrl = getApiBase()
      setMaintenanceStatus('Running nuclear flush...')
      const flushResponse = await authFetch(`${baseUrl}/admin/maintenance/flush`, {
        method: 'POST',
      })
      if (!flushResponse.ok) {
        const text = await flushResponse.text()
        throw new Error(text || 'Flush failed')
      }
      const flushData = await flushResponse.json()
      const usersCleared = Number(flushData?.userObjectsCleared?.users ?? 0)
      setMaintenanceStatus(`Nuclear flush complete. Cleared ${usersCleared} non-admin users. Re-syncing users...`)
      const usersResyncResponse = await authFetch(`${baseUrl}/admin/jellyseerr/users/resync`, {
        method: 'POST',
      })
      if (!usersResyncResponse.ok) {
        const text = await usersResyncResponse.text()
        throw new Error(text || 'User resync failed')
      }
      const usersResyncData = await usersResyncResponse.json()
      setMaintenanceStatus(
        `Users re-synced (${usersResyncData?.imported ?? 0} imported). Starting request re-sync...`
      )
      await syncRequests()
      setMaintenanceStatus('Nuclear flush complete. User and request re-sync running now.')
    } catch (err) {
      console.error(err)
      setMaintenanceStatus('Nuclear flush + resync failed.')
    } finally {
      setMaintenanceBusy(false)
    }
  }

  const clearLogFile = async () => {
    setMaintenanceStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/admin/maintenance/logs/clear`, {
        method: 'POST',
      })
      if (!response.ok) {
        const text = await response.text()
        throw new Error(text || 'Clear logs failed')
      }
      setMaintenanceStatus('Log file cleared.')
      setLogsLines([])
    } catch (err) {
      console.error(err)
      setMaintenanceStatus('Clearing logs failed.')
    }
  }

  const cacheSourceLabel =
    formValues.requests_data_source === 'always_js'
      ? 'Seerr direct'
      : formValues.requests_data_source === 'prefer_cache'
        ? 'Saved requests only'
        : 'Saved requests only'
  const cacheTtlLabel = formValues.requests_sync_ttl_minutes || '60'
  const maintenanceRail = showMaintenance ? (
    <div className="admin-rail-stack">
      <div className="admin-rail-card">
        <span className="admin-rail-eyebrow">Maintenance</span>
        <h2>Admin tools</h2>
        <p>Repair, cleanup, diagnostics, and nuclear resync are grouped into a single operating page.</p>
      </div>
      <div className="admin-rail-card cache-rail-card">
        <span className="admin-rail-eyebrow">Runtime</span>
        <h2>Service state</h2>
        <div className="cache-rail-metrics">
          <div className="cache-rail-metric">
            <span>Maintenance job</span>
            <strong>{maintenanceBusy ? 'Running' : 'Idle'}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Live updates</span>
            <strong>{liveStreamConnected ? 'Connected' : 'Polling'}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Log lines in view</span>
            <strong>{logsLines.length}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Last tool status</span>
            <strong>{maintenanceStatus || 'Idle'}</strong>
          </div>
        </div>
      </div>
    </div>
  ) : undefined
  const cacheRail = showCacheExtras ? (
    <div className="admin-rail-stack">
      <div className="admin-rail-card cache-rail-card">
        <span className="admin-rail-eyebrow">Cache control</span>
        <h2>Saved requests</h2>
        <p>Load and inspect cached request entries from the right rail.</p>
        <div className="cache-rail-metrics">
          <div className="cache-rail-metric">
            <span>Data source</span>
            <strong>{cacheSourceLabel}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Refresh TTL</span>
            <strong>{cacheTtlLabel} min</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Rows loaded</span>
            <strong>{cacheRows.length}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Live updates</span>
            <strong>{liveStreamConnected ? 'Connected' : 'Polling'}</strong>
          </div>
        </div>
        <label className="cache-rail-limit">
          <span>Rows to load</span>
          <select
            value={cacheCount}
            onChange={(event) => setCacheCount(Number(event.target.value))}
          >
            <option value={25}>25</option>
            <option value={50}>50</option>
            <option value={100}>100</option>
            <option value={200}>200</option>
          </select>
        </label>
        <button type="button" onClick={loadCache} disabled={cacheLoading}>
          {cacheLoading ? (
            <>
              <span className="spinner button-spinner" aria-hidden="true" />
              Loading saved requests
            </>
          ) : (
            'Load saved requests'
          )}
        </button>
        {cacheStatus && <div className="error-banner">{cacheStatus}</div>}
      </div>
      <div className="admin-rail-card cache-rail-card">
        <span className="admin-rail-eyebrow">Artwork</span>
        <h2>Cache stats</h2>
        <div className="cache-rail-metrics">
          <div className="cache-rail-metric">
            <span>Missing artwork</span>
            <strong>{artworkSummary?.missing_artwork ?? '--'}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Cache size</span>
            <strong>{formatBytes(artworkSummary?.cache_bytes)}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Cached files</span>
            <strong>{artworkSummary?.cache_files ?? '--'}</strong>
          </div>
          <div className="cache-rail-metric">
            <span>Mode</span>
            <strong>{artworkSummary?.cache_mode ?? '--'}</strong>
          </div>
        </div>
      </div>
    </div>
  ) : undefined

  if (loading) {
    return <main className="card">Loading admin settings...</main>
  }

  return (
    <AdminShell
      title={SECTION_LABELS[section] ?? 'Settings'}
      subtitle={SECTION_DESCRIPTIONS[section] ?? 'Manage settings.'}
      rail={maintenanceRail ?? cacheRail}
      actions={
        <button type="button" onClick={() => router.push('/admin')}>
          Back to settings
        </button>
      }
    >
      {status && <div className="error-banner">{status}</div>}
      {settingsSections.length > 0 ? (
      <div className="admin-form">
        {settingsSections
          .filter(shouldRenderSection)
          .map((sectionGroup) => (
          <section key={sectionGroup.key} className="admin-section">
            <div className="section-header">
              <h2>
                {sectionGroup.key === 'requests' ? 'Request sync controls' : sectionGroup.title}
              </h2>
              {sectionGroup.key === 'sonarr' && (
                <button type="button" onClick={() => loadOptions('sonarr')}>
                  Refresh Sonarr options
                </button>
              )}
              {sectionGroup.key === 'radarr' && (
                <button type="button" onClick={() => loadOptions('radarr')}>
                  Refresh Radarr options
                </button>
              )}
              {sectionGroup.key === 'jellyfin' && (
                <button type="button" onClick={syncJellyfinUsers}>
                  Import Jellyfin users
                </button>
              )}
              {showArtworkExtras && sectionGroup.key === 'artwork' ? (
                <div className="sync-actions">
                  <button type="button" onClick={prefetchArtwork}>
                    Cache all artwork now
                  </button>
                  <button
                    type="button"
                    className="ghost-button"
                    onClick={prefetchArtworkMissing}
                  >
                    Sync only missing artwork
                  </button>
                </div>
              ) : null}
              {showRequestsExtras && sectionGroup.key === 'requests' && (
                <div className="sync-actions-block">
                  <div className="sync-actions">
                    <button type="button" onClick={syncRequests}>
                      Run full refresh (rebuild cache)
                    </button>
                    <button type="button" className="ghost-button" onClick={syncRequestsDelta}>
                      Run delta sync (recent changes)
                    </button>
                  </div>
                  <div className="meta sync-note">
                    Full refresh rebuilds the entire cache. Delta sync only checks new or updated
                    requests.
                  </div>
                </div>
              )}
            </div>
            {(sectionGroup.description || SECTION_DESCRIPTIONS[sectionGroup.key]) &&
              (!settingsSection || isMagentGroupedSection) && (
                <p className="section-subtitle">
                  {sectionGroup.description || SECTION_DESCRIPTIONS[sectionGroup.key]}
                </p>
              )}
            {section === 'general' && sectionGroup.key === 'magent-runtime' && (
              <div className="status-banner">
                Runtime host/port and SSL values are configuration settings. Container/process
                restarts may still be required before bind/port changes take effect.
              </div>
            )}
            {sectionGroup.key === 'sonarr' && sonarrError && (
              <div className="error-banner">{sonarrError}</div>
            )}
            {sectionGroup.key === 'radarr' && radarrError && (
              <div className="error-banner">{radarrError}</div>
            )}
            {sectionGroup.key === 'jellyfin' && jellyfinSyncStatus && (
              <div className="status-banner">{jellyfinSyncStatus}</div>
            )}
            {showArtworkExtras && sectionGroup.key === 'artwork' && artworkPrefetchStatus && (
              <div className="status-banner">{artworkPrefetchStatus}</div>
            )}
            {showArtworkExtras && sectionGroup.key === 'artwork' && artworkSummaryStatus && (
              <div className="status-banner">{artworkSummaryStatus}</div>
            )}
            {showArtworkExtras && sectionGroup.key === 'artwork' && (
              <div className="summary">
                <div className="summary-card">
                  <strong>Missing artwork</strong>
                  <p>{artworkSummary?.missing_artwork ?? '--'}</p>
                  <div className="meta">Requests missing poster/backdrop or cache files.</div>
                </div>
                <div className="summary-card">
                  <strong>Artwork cache size</strong>
                  <p>{formatBytes(artworkSummary?.cache_bytes)}</p>
                  <div className="meta">
                    {artworkSummary?.cache_files ?? '--'} cached files
                  </div>
                </div>
                <div className="summary-card">
                  <strong>Total requests</strong>
                  <p>{artworkSummary?.total_requests ?? '--'}</p>
                  <div className="meta">Requests currently tracked in cache.</div>
                </div>
                <div className="summary-card">
                  <strong>Cache mode</strong>
                  <p>{artworkSummary?.cache_mode ?? '--'}</p>
                  <div className="meta">Artwork setting applied to posters/backdrops.</div>
                </div>
              </div>
            )}
            {showRequestsExtras && sectionGroup.key === 'requests' && requestsSyncStatus && (
              <div className="status-banner">{requestsSyncStatus}</div>
            )}
            {showRequestsExtras && sectionGroup.key === 'requests' && (
              <div className="status-banner">
                Full refresh checks only decide when to run a full refresh. The delta sync interval
                polls for new or updated requests.
              </div>
            )}
            {showArtworkExtras && sectionGroup.key === 'artwork' && artworkPrefetch && (
              <div className="sync-progress">
                <div className="sync-meta">
                  <span>Status: {artworkPrefetch.status}</span>
                  <span>
                    {artworkPrefetch.processed ?? 0}
                    {artworkPrefetch.total ? ` / ${artworkPrefetch.total}` : ''} cached
                  </span>
                </div>
                <div
                  className={`progress ${artworkPrefetch.status === 'completed' ? 'progress-complete' : ''}`}
                >
                  <div
                    className="progress-fill"
                    style={{
                      width: `${computeProgressPercent(
                        artworkPrefetch.processed,
                        artworkPrefetch.total,
                        artworkPrefetch.status
                      )}%`,
                    }}
                  />
                </div>
                {artworkPrefetch.message && <div className="meta">{artworkPrefetch.message}</div>}
              </div>
            )}
            {showRequestsExtras && sectionGroup.key === 'requests' && requestsSync && (
              <div className="sync-progress">
                <div className="sync-meta">
                  <span>Status: {requestsSync.status}</span>
                  <span>
                    {requestsSync.stored ?? 0}
                    {requestsSync.total ? ` / ${requestsSync.total}` : ''} synced
                  </span>
                </div>
                <div
                  className={`progress ${requestsSync.status === 'completed' ? 'progress-complete' : ''}`}
                >
                  <div
                    className="progress-fill"
                    style={{
                      width: `${computeProgressPercent(
                        requestsSync.stored,
                        requestsSync.total,
                        requestsSync.status
                      )}%`,
                    }}
                  />
                </div>
                {requestsSync.message && <div className="meta">{requestsSync.message}</div>}
              </div>
            )}
            <div className="admin-grid">
              {sectionGroup.items.map((setting) => {
                const value = formValues[setting.key] ?? ''
                const helperText = settingDescriptions[setting.key]
                const isSonarrProfile = setting.key === 'sonarr_quality_profile_id'
                const isSonarrRoot = setting.key === 'sonarr_root_folder'
                const isRadarrProfile = setting.key === 'radarr_quality_profile_id'
                const isRadarrRoot = setting.key === 'radarr_root_folder'
                const isBoolSetting = BOOL_SETTINGS.has(setting.key)
                const isUrlSetting = URL_SETTINGS.has(setting.key)
                const inputPlaceholder = setting.sensitive && setting.isSet
                  ? 'Configured (enter to replace)'
                  : settingPlaceholders[setting.key] ?? ''
                if (isBoolSetting) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value || 'false'}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="true">Enabled</option>
                        <option value="false">Disabled</option>
                      </select>
                    </label>
                  )
                }
                if (isSonarrProfile && sonarrOptions) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                    <span className="meta">
                      {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                      {setting.sensitive && setting.isSet ? ' • stored' : ''}
                    </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="">Select a quality profile</option>
                        {buildSelectOptions(value, sonarrOptions.qualityProfiles, false)}
                      </select>
                    </label>
                  )
                }
                if (isSonarrRoot && sonarrOptions) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                          {setting.sensitive && setting.isSet ? ' • stored' : ''}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="">Select a root folder</option>
                        {buildSelectOptions(value, sonarrOptions.rootFolders, true)}
                      </select>
                    </label>
                  )
                }
                if (isRadarrProfile && radarrOptions) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                          {setting.sensitive && setting.isSet ? ' • stored' : ''}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="">Select a quality profile</option>
                        {buildSelectOptions(value, radarrOptions.qualityProfiles, false)}
                      </select>
                    </label>
                  )
                }
                if (isRadarrRoot && radarrOptions) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                          {setting.sensitive && setting.isSet ? ' • stored' : ''}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="">Select a root folder</option>
                        {buildSelectOptions(value, radarrOptions.rootFolders, true)}
                      </select>
                    </label>
                  )
                }
                if (setting.key === 'log_level') {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="DEBUG">DEBUG</option>
                        <option value="INFO">INFO</option>
                        <option value="WARNING">WARNING</option>
                        <option value="ERROR">ERROR</option>
                      </select>
                    </label>
                  )
                }
                if (
                  setting.key === 'log_http_client_level' ||
                  setting.key === 'log_background_sync_level'
                ) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value || 'INFO'}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="DEBUG">DEBUG</option>
                        <option value="INFO">INFO</option>
                        <option value="WARNING">WARNING</option>
                        <option value="ERROR">ERROR</option>
                      </select>
                    </label>
                  )
                }
                if (setting.key === 'artwork_cache_mode') {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value || 'remote'}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="remote">Pull from the internet</option>
                        <option value="cache">Cache locally</option>
                      </select>
                    </label>
                  )
                }
                if (setting.key === 'site_banner_tone') {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value || 'info'}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        {BANNER_TONES.map((tone) => (
                          <option key={tone} value={tone}>
                            {tone.charAt(0).toUpperCase() + tone.slice(1)}
                          </option>
                        ))}
                      </select>
                    </label>
                  )
                }
                if (setting.key === 'magent_notify_push_provider') {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value || 'ntfy'}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="ntfy">ntfy</option>
                        <option value="gotify">Gotify</option>
                        <option value="pushover">Pushover</option>
                        <option value="webhook">Webhook</option>
                        <option value="telegram">Telegram relay</option>
                        <option value="discord">Discord relay</option>
                      </select>
                    </label>
                  )
                }
                if (
                  setting.key === 'requests_full_sync_time' ||
                  setting.key === 'requests_cleanup_time'
                ) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <input
                        name={setting.key}
                        type="time"
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      />
                    </label>
                  )
                }
                if (NUMBER_SETTINGS.has(setting.key)) {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <input
                        name={setting.key}
                        type="number"
                        min={1}
                        step={1}
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      />
                    </label>
                  )
                }
                if (setting.key === 'requests_data_source') {
                  return (
                    <label key={setting.key} data-helper={helperText || undefined}>
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                        </span>
                      </span>
                      <select
                        name={setting.key}
                        value={value || 'prefer_cache'}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      >
                        <option value="always_js">Always use Seerr (slower)</option>
                        <option value="prefer_cache">
                          Use saved requests only (fastest)
                        </option>
                      </select>
                    </label>
                  )
                }
                if (TEXTAREA_SETTINGS.has(setting.key)) {
                  const isPemField =
                    setting.key === 'magent_ssl_certificate_pem' ||
                    setting.key === 'magent_ssl_private_key_pem'
                  return (
                    <label
                      key={setting.key}
                      data-helper={helperText || undefined}
                      className={isPemField ? 'field-span-full' : undefined}
                    >
                      <span className="label-row">
                        <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                          {setting.sensitive && setting.isSet ? '  stored' : ''}
                        </span>
                      </span>
                      <textarea
                        name={setting.key}
                        rows={setting.key === 'site_changelog' ? 6 : isPemField ? 8 : 3}
                        placeholder={
                          setting.key === 'site_changelog'
                            ? 'One update per line.'
                            : settingPlaceholders[setting.key] ?? ''
                        }
                        value={value}
                        onChange={(event) =>
                          setFormValues((current) => ({
                            ...current,
                            [setting.key]: event.target.value,
                          }))
                        }
                      />
                    </label>
                  )
                }
                return (
                  <label key={setting.key} data-helper={helperText || undefined}>
                    <span className="label-row">
                      <span>{labelFromKey(setting.key)}</span>
                        <span className="meta">
                          {setting.isSet ? `Source: ${setting.source}` : 'Not set'}
                          {setting.sensitive && setting.isSet ? ' • stored' : ''}
                        </span>
                    </span>
                    <input
                      name={setting.key}
                      type={setting.sensitive ? 'password' : 'text'}
                      placeholder={inputPlaceholder}
                      autoComplete={isUrlSetting ? 'url' : undefined}
                      value={value}
                      onChange={(event) =>
                        setFormValues((current) => ({
                          ...current,
                          [setting.key]: event.target.value,
                        }))
                      }
                    />
                  </label>
                )
              })}
            </div>
            {sectionFeedback[sectionGroup.key] && (
              <div
                className={
                  sectionFeedback[sectionGroup.key]?.tone === 'error'
                    ? 'error-banner'
                    : 'status-banner'
                }
              >
                {sectionFeedback[sectionGroup.key]?.message}
              </div>
            )}
            <div className="settings-section-actions">
              {sectionGroup.key === 'magent-notify-email' ? (
                <label className="settings-inline-field">
                  <span>Test email recipient</span>
                  <input
                    type="email"
                    placeholder="Leave blank to use the configured sender"
                    value={emailTestRecipient}
                    onChange={(event) => setEmailTestRecipient(event.target.value)}
                  />
                </label>
              ) : null}
              <button
                type="button"
                onClick={() => void saveSettingGroup(sectionGroup)}
                disabled={sectionSaving[sectionGroup.key] || sectionTesting[sectionGroup.key]}
              >
                {sectionSaving[sectionGroup.key] ? 'Saving...' : 'Save section'}
              </button>
              {getSectionTestLabel(sectionGroup.key) ? (
                <button
                  type="button"
                  className="ghost-button"
                  onClick={() => void testSettingGroup(sectionGroup)}
                  disabled={sectionSaving[sectionGroup.key] || sectionTesting[sectionGroup.key]}
                >
                  {sectionTesting[sectionGroup.key]
                    ? 'Testing...'
                    : getSectionTestLabel(sectionGroup.key)}
                </button>
              ) : null}
            </div>
          </section>
        ))}
      </div>
      ) : (
      <div className="status-banner">
        {section === 'magent'
          ? 'Magent runtime settings have moved to General. Notification provider settings have moved to Notifications.'
          : 'No settings to show here yet. Try the Cache Control page for artwork and saved-request controls.'}
      </div>
      )}
      {showLogs && (
      <section className="admin-section" id="logs">
        <div className="section-header">
          <h2>Activity log</h2>
          <div className="log-actions">
            <label className="recent-filter">
              <span>Lines to show</span>
              <select
                value={logsCount}
                onChange={(event) => setLogsCount(Number(event.target.value))}
              >
                <option value={100}>100</option>
                <option value={200}>200</option>
                <option value={500}>500</option>
                <option value={1000}>1000</option>
              </select>
            </label>
            <button type="button" onClick={loadLogs}>
              Refresh log
            </button>
          </div>
        </div>
        {logsStatus && <div className="error-banner">{logsStatus}</div>}
        <pre className="log-viewer">{logsLines.join('')}</pre>
      </section>
      )}
      {showCacheExtras && (
      <section className="admin-section" id="cache">
        <div className="section-header">
          <h2>Saved requests (cache)</h2>
        </div>
        <div className="cache-table">
          <div className="cache-row cache-head">
            <span>Request</span>
            <span>Title</span>
            <span>Type</span>
            <span>Status</span>
            <span>Last update</span>
          </div>
          {cacheRows.length === 0 ? (
            <div className="meta">No saved requests loaded yet.</div>
          ) : (
            cacheRows.map((row) => (
              <div key={row.request_id} className="cache-row">
                <span>#{row.request_id}</span>
                <span>{row.title || 'Untitled'}</span>
                <span>{row.media_type || 'unknown'}</span>
                <span>{row.status ?? 'n/a'}</span>
                <span>{row.updated_at || row.created_at || 'n/a'}</span>
              </div>
            ))
          )}
        </div>
      </section>
      )}
      {showMaintenance && (
      <section className="admin-section" id="maintenance">
        <div className="section-header">
          <h2>Maintenance</h2>
        </div>
        <div className="maintenance-layout">
          <div className="admin-panel maintenance-tools-panel">
            <div className="maintenance-panel-copy">
              <h3>Recovery and cleanup</h3>
              <p className="lede">
                Run repair, cleanup, logging, and full reset actions from one place. Nuclear flush
                wipes non-admin users, invite links, profiles, cached requests, and history before
                re-syncing Seerr users and requests.
              </p>
            </div>
            <div className="status-banner">
              Emergency tools. Use with care, especially on live data.
            </div>
            {maintenanceStatus && <div className="status-banner">{maintenanceStatus}</div>}
            <div className="maintenance-action-grid">
              <div className="maintenance-action-card">
                <div className="maintenance-action-copy">
                  <h3>Repair database</h3>
                  <p>Run integrity and repair routines against the local Magent database.</p>
                </div>
                <button type="button" onClick={runRepair}>
                  Repair database
                </button>
              </div>
              <div className="maintenance-action-card">
                <div className="maintenance-action-copy">
                  <h3>Clean request history</h3>
                  <p>Remove request history entries older than 90 days.</p>
                </div>
                <button type="button" className="ghost-button" onClick={runCleanup}>
                  Clean history
                </button>
              </div>
              <div className="maintenance-action-card">
                <div className="maintenance-action-copy">
                  <h3>Clear activity log</h3>
                  <p>Truncate the local activity log file so fresh troubleshooting starts clean.</p>
                </div>
                <button type="button" className="ghost-button" onClick={clearLogFile}>
                  Clear activity log
                </button>
              </div>
              <div className="maintenance-action-card maintenance-action-card-danger">
                <div className="maintenance-action-copy">
                  <h3>Nuclear flush + resync</h3>
                  <p>Wipe non-admin user and request objects, then rebuild from Seerr.</p>
                </div>
                <button
                  type="button"
                  className="danger-button"
                  onClick={runFlushAndResync}
                  disabled={maintenanceBusy}
                >
                  {maintenanceBusy ? 'Running...' : 'Nuclear flush + resync'}
                </button>
              </div>
            </div>
          </div>
          <AdminDiagnosticsPanel embedded />
        </div>
      </section>
      )}
      {showRequestsExtras && (
      <section className="admin-section" id="schedules">
        <div className="section-header">
          <h2>Scheduled tasks</h2>
        </div>
        <div className="status-banner">
          Automated jobs keep requests and housekeeping up to date.
        </div>
        <div className="schedule-grid">
          <div className="schedule-card">
            <h3>Quick request check</h3>
            <p>
              Every {formValues.requests_delta_sync_interval_minutes || '5'} minutes, checks for
              new or updated requests.
            </p>
          </div>
          <div className="schedule-card">
            <h3>Full daily refresh</h3>
            <p>
              Every day at {formValues.requests_full_sync_time || '00:00'}, refreshes the entire
              requests list.
            </p>
          </div>
          <div className="schedule-card">
            <h3>History cleanup</h3>
            <p>
              Every day at {formValues.requests_cleanup_time || '02:00'}, removes history older
              than {formValues.requests_cleanup_days || '90'} days.
            </p>
          </div>
        </div>
      </section>
      )}
    </AdminShell>
  )
}
