import React, { useState, useEffect, useRef } from 'react'
import { useSearchParams, Link } from 'react-router-dom'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useBreadcrumb } from '../hooks/useBreadcrumb'
import { breadcrumbConfig } from '../config/breadcrumbConfig'
import {
  User,
  Instagram,
  Download,
  Info,
  Key,
  Save,
  CheckCircle,
  Package,
  Lock,
  Trash2,
  Shield,
  Smartphone,
  Copy,
  Download as DownloadIcon,
  Fingerprint,
  Monitor,
  Video,
  Upload,
  Plus,
  X,
  Sparkles,
  RefreshCw,
  RefreshCcw,
  Loader2,
  Settings,
  Layers,
  Calendar,
  UserPlus,
  Mic,
  Play,
  Link2 as LinkIcon,
  Film,
  Clock,
  CreditCard,
  Heart,
  Wrench,
  FolderInput,
  Search,
  CheckSquare,
  Square,
  MinusSquare,
  Cloud,
  RotateCw,
  Pause,
  Eye,
  EyeOff,
  Unlock,
  Newspaper,
} from 'lucide-react'
import UsernameListEditor from '../components/UsernameListEditor'
import InstagramUnified, { type InstagramUnifiedRef } from './InstagramUnified'
import { api, wsClient } from '../lib/api'
import { notificationManager } from '../lib/notificationManager'
import {
  ChevronRight,
  GripVertical,
  ListVideo,
  Users,
  FileText,
  MessageCircle,
} from 'lucide-react'

type TabType = 'account' | 'platforms' | 'downloads' | 'face_recognition' | 'ai_search' | 'manual_import' | 'monitoring' | 'cloud_backup' | 'dependencies' | 'appearances' | 'press' | 'features' | 'modules' | 'about'

export default function Configuration() {
  useBreadcrumb(breadcrumbConfig['/config'])
  const [searchParams] = useSearchParams()
  const tabParam = searchParams.get('tab')
  // If tab=youtube_monitors, go to platforms tab (youtube_monitors is a sub-tab)
  const initialTab = tabParam === 'youtube_monitors' ? 'platforms' : (tabParam as TabType | null)
  const validTabs: TabType[] = ['account', 'platforms', 'downloads', 'face_recognition', 'ai_search', 'manual_import', 'monitoring', 'cloud_backup', 'dependencies', 'appearances', 'press', 'features', 'about']
  const [activeTab, setActiveTab] = useState<TabType>(
    initialTab && validTabs.includes(initialTab) ? initialTab : 'account'
  )

  const tabs = [
    { id: 'account' as TabType, label: 'Account & Security', icon: User },
    { id: 'platforms' as TabType, label: 'Platforms', icon: Instagram },
    { id: 'downloads' as TabType, label: 'Downloads', icon: Download },
    { id: 'face_recognition' as TabType, label: 'Face Recognition', icon: Fingerprint },
    { id: 'ai_search' as TabType, label: 'AI Search', icon: Sparkles },
    { id: 'manual_import' as TabType, label: 'Manual Import', icon: Upload },
    { id: 'monitoring' as TabType, label: 'Monitoring', icon: Monitor },
    { id: 'cloud_backup' as TabType, label: 'Cloud Backup', icon: Cloud },
    { id: 'dependencies' as TabType, label: 'Dependencies', icon: Package },
    { id: 'appearances' as TabType, label: 'Appearances', icon: Calendar },
    { id: 'press' as TabType, label: 'Press', icon: Newspaper },
    { id: 'features' as TabType, label: 'Features', icon: Shield },
    { id: 'modules' as TabType, label: 'Modules', icon: Layers },
    { id: 'about' as TabType, label: 'About', icon: Info },
  ]

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl sm:text-3xl font-bold flex items-center gap-2 sm:gap-3">
          <Settings className="w-8 h-8 text-slate-500" />
          Configuration
        </h1>
        <p className="text-slate-600 dark:text-slate-400 mt-1">
          Manage your settings, security, and platform configurations
        </p>
      </div>

      {/* Tabs */}
      <div className="border-b border-slate-200 dark:border-slate-700">
        <div className="flex space-x-1 overflow-x-auto custom-scrollbar">
          {tabs.map((tab) => {
            const Icon = tab.icon
            return (
              <button
                key={tab.id}
                onClick={() => setActiveTab(tab.id)}
                className={`flex items-center space-x-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
                  activeTab === tab.id
                    ? 'border-blue-600 text-blue-600 dark:text-blue-400'
                    : 'border-transparent text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100'
                }`}
              >
                <Icon className="w-4 h-4" />
                <span>{tab.label}</span>
              </button>
            )
          })}
        </div>
      </div>

      {/* Tab Content */}
      <div className="card-glass rounded-xl p-6">
        {activeTab === 'account' && <AccountSecurityTab />}
        {activeTab === 'platforms' && <PlatformsTab />}
        {activeTab === 'downloads' && <DownloadsTab />}
        {activeTab === 'face_recognition' && <FaceRecognitionTab />}
        {activeTab === 'ai_search' && <AISearchTab />}
        {activeTab === 'manual_import' && <ManualImportTab />}
        {activeTab === 'monitoring' && <MonitoringTab />}
        {activeTab === 'cloud_backup' && <CloudBackupTab />}
        {activeTab === 'dependencies' && <DependenciesTab />}
        {activeTab === 'appearances' && <AppearancesTab />}
        {activeTab === 'press' && <PressTab />}
        {activeTab === 'features' && <FeaturesTab />}
        {activeTab === 'modules' && <ModulesTab />}
        {activeTab === 'about' && <AboutTab />}
      </div>
    </div>
  )
}

// Account & Security Tab
function AccountSecurityTab() {
  // User info
  const { data: userInfo } = useQuery({
    queryKey: ['user-info'],
    queryFn: () => api.getMe(),
  })

  // Change password
  const changePasswordMutation = useMutation({
    mutationFn: ({ currentPassword, newPassword }: { currentPassword: string; newPassword: string }) =>
      api.changePassword(currentPassword, newPassword),
    onSuccess: () => {
      alert('Password changed successfully!')
    },
    onError: (error: any) => {
      console.error('Failed to change password:', error)
      alert('Failed to change password: ' + (error.message || 'Unknown error'))
    },
  })

  const handleChangePassword = async () => {
    const currentPassword = prompt('Enter your current password:')
    if (!currentPassword) return

    const newPassword = prompt('Enter your new password:')
    if (!newPassword) return

    const confirmPassword = prompt('Confirm your new password:')
    if (confirmPassword !== newPassword) {
      alert('Passwords do not match')
      return
    }

    changePasswordMutation.mutate({ currentPassword, newPassword })
  }

  return (
    <div className="space-y-6">
      {/* Account Information */}
      <div>
        <h2 className="text-xl font-semibold text-slate-900 dark:text-slate-100 mb-4">
          <User className="w-5 h-5 inline mr-2" />
          Account Information
        </h2>
        <div className="bg-secondary/50 rounded-lg p-6 space-y-4">
          <div>
            <label className="block text-sm font-medium text-foreground mb-1">
              Username
            </label>
            <input
              type="text"
              value={userInfo?.username || ''}
              disabled
              className="w-full px-3 py-2 bg-secondary border border-border rounded-lg text-foreground"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-foreground mb-1">
              Role
            </label>
            <input
              type="text"
              value={userInfo?.role || ''}
              disabled
              className="w-full px-3 py-2 bg-secondary border border-border rounded-lg text-foreground"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-foreground mb-1">
              Email
            </label>
            <input
              type="email"
              value={userInfo?.email || ''}
              disabled
              className="w-full px-3 py-2 bg-secondary border border-border rounded-lg text-foreground"
            />
          </div>
        </div>
      </div>

      {/* Password Change */}
      <div>
        <h2 className="text-xl font-semibold text-foreground mb-4">
          <Lock className="w-5 h-5 inline mr-2" />
          Change Password
        </h2>
        <div className="bg-secondary/50 rounded-lg p-6">
          <p className="text-sm text-muted-foreground mb-4">
            Update your password to keep your account secure.
          </p>
          <button
            onClick={handleChangePassword}
            disabled={changePasswordMutation.isPending}
            className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded-lg transition-colors flex items-center gap-2"
          >
            <Key className="w-4 h-4" />
            <span>{changePasswordMutation.isPending ? 'Changing...' : 'Change Password'}</span>
          </button>
        </div>
      </div>

      {/* Two-Factor Authentication */}
      <TwoFactorAuthSection />
    </div>
  )
}

// Two-Factor Authentication Section
function TwoFactorAuthSection() {
  const [setupMethod, setSetupMethod] = useState<'totp' | 'duo' | 'passkey' | null>(null)
  const [totpSetupData, setTotpSetupData] = useState<any>(null)
  const [totpVerifyCode, setTotpVerifyCode] = useState('')
  const [backupCodes, setBackupCodes] = useState<string[]>([])
  const [passkeyName, setPasskeyName] = useState('')
  const [enrollingPasskey, setEnrollingPasskey] = useState(false)

  // Get 2FA status
  const { data: twoFAStatus, refetch: refetch2FAStatus } = useQuery({
    queryKey: ['2fa-status'],
    queryFn: () => api.get2FAStatus(),
  })

  // Get passkey list
  const { data: passkeyList, refetch: refetchPasskeyList } = useQuery({
    queryKey: ['passkey-list'],
    queryFn: () => api.get('/auth/2fa/passkey/list'),
    enabled: !!(twoFAStatus as any)?.passkey?.enabled,
  })

  // Setup TOTP
  const setupTOTPMutation = useMutation({
    mutationFn: () => api.setupTOTP(),
    onSuccess: (data: any) => {
      setTotpSetupData(data)
      setSetupMethod('totp')
    },
    onError: (error: any) => {
      alert('Failed to setup TOTP: ' + (error.message || 'Unknown error'))
    },
  })

  // Verify and enable TOTP
  const enableTOTPMutation = useMutation({
    mutationFn: (code: string) => api.verifyTOTP(code),
    onSuccess: (data: any) => {
      if (data.success) {
        setBackupCodes(data.backupCodes || [])
        alert('TOTP enabled successfully! Save your backup codes.')
        refetch2FAStatus()
        setSetupMethod(null)
        setTotpSetupData(null)
        setTotpVerifyCode('')
      } else {
        alert('Invalid code. Please try again.')
      }
    },
    onError: (error: any) => {
      alert('Failed to verify TOTP: ' + (error.message || 'Unknown error'))
    },
  })

  // Disable TOTP
  const disableTOTPMutation = useMutation({
    mutationFn: ({ password, code }: { password: string; code: string }) => api.disableTOTP(password, code),
    onSuccess: () => {
      alert('TOTP disabled successfully')
      refetch2FAStatus()
    },
    onError: (error: any) => {
      alert('Failed to disable TOTP: ' + (error.message || 'Unknown error'))
    },
  })

  // Enroll in Duo
  const enrollDuoMutation = useMutation({
    mutationFn: (duoUsername: string) => api.enrollDuo(duoUsername),
    onSuccess: () => {
      alert('Duo enrolled successfully')
      refetch2FAStatus()
      setSetupMethod(null)
    },
    onError: (error: any) => {
      alert('Failed to enroll in Duo: ' + (error.message || 'Unknown error'))
    },
  })

  // Disable Duo
  const disableDuoMutation = useMutation({
    mutationFn: () => api.unenrollDuo(),
    onSuccess: () => {
      alert('Duo disabled successfully')
      refetch2FAStatus()
    },
    onError: (error: any) => {
      alert('Failed to disable Duo: ' + (error.message || 'Unknown error'))
    },
  })

  const handleEnableTOTP = () => {
    setupTOTPMutation.mutate()
  }

  const handleVerifyTOTP = () => {
    if (!totpVerifyCode) {
      alert('Please enter the 6-digit code')
      return
    }
    enableTOTPMutation.mutate(totpVerifyCode)
  }

  const handleDisableTOTP = () => {
    if (confirm('Are you sure you want to disable TOTP authentication?')) {
      const password = prompt('Enter your password:')
      if (!password) return
      const code = prompt('Enter your current TOTP code:')
      if (!code) return
      disableTOTPMutation.mutate({ password, code })
    }
  }

  const handleEnrollDuo = () => {
    // Pass undefined to use the user's account username by default
    enrollDuoMutation.mutate(undefined as any)
  }

  const handleDisableDuo = () => {
    if (confirm('Are you sure you want to disable Duo authentication?')) {
      disableDuoMutation.mutate()
    }
  }

  // Passkey enrollment
  const handleEnrollPasskey = async () => {
    setSetupMethod('passkey')
  }

  const handlePasskeyEnrollment = async () => {
    if (!passkeyName.trim()) {
      alert('Please enter a name for this passkey')
      return
    }

    setEnrollingPasskey(true)
    try {
      // Get registration options from server
      const optionsResult: any = await api.getPasskeyRegistrationOptions()

      if (!optionsResult.success) {
        throw new Error(optionsResult.message || 'Failed to get registration options')
      }

      // The options are already in the correct format from the webauthn library
      // We just need to convert base64url strings to Uint8Arrays
      const options = optionsResult.options

      // Helper to convert base64url to Uint8Array
      const base64urlToUint8Array = (base64url: string): Uint8Array => {
        // Convert base64url to base64
        const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/')
        // Decode base64 to binary string
        const binaryString = atob(base64)
        // Convert binary string to Uint8Array
        const bytes = new Uint8Array(binaryString.length)
        for (let i = 0; i < binaryString.length; i++) {
          bytes[i] = binaryString.charCodeAt(i)
        }
        return bytes
      }

      const publicKeyOptions = {
        ...options,
        challenge: base64urlToUint8Array(options.challenge),
        user: {
          ...options.user,
          id: base64urlToUint8Array(options.user.id)
        },
        excludeCredentials: options.excludeCredentials?.map((cred: any) => ({
          ...cred,
          id: base64urlToUint8Array(cred.id)
        }))
      }

      // Request credential from browser
      const credential = await navigator.credentials.create({
        publicKey: publicKeyOptions
      }) as any

      if (!credential) {
        throw new Error('Passkey creation was cancelled')
      }

      // Convert credential to base64 for transmission
      const credentialData = {
        id: credential.id,
        rawId: arrayBufferToBase64(credential.rawId),
        response: {
          clientDataJSON: arrayBufferToBase64(credential.response.clientDataJSON),
          attestationObject: arrayBufferToBase64(credential.response.attestationObject)
        },
        type: credential.type
      }

      // Send to server for verification
      const verifyResult: any = await api.post('/auth/2fa/passkey/verify-registration', {
        credential: credentialData,
        deviceName: passkeyName
      })

      if (verifyResult.success) {
        alert('Passkey registered successfully!')
        setSetupMethod(null)
        setPasskeyName('')
        refetch2FAStatus()
        refetchPasskeyList()
      } else {
        throw new Error(verifyResult.message || 'Failed to verify passkey')
      }
    } catch (err: any) {
      console.error('Passkey enrollment error:', err)
      alert('Failed to enroll passkey: ' + (err.message || 'Unknown error'))
    } finally {
      setEnrollingPasskey(false)
    }
  }

  const handleRemovePasskey = async (credentialId: string, name: string) => {
    if (!confirm(`Remove passkey "${name}"?`)) return

    try {
      const result: any = await api.delete(`/auth/2fa/passkey/${credentialId}`)
      if (result.success) {
        alert('Passkey removed successfully')
        refetch2FAStatus()
        refetchPasskeyList()
      } else {
        throw new Error(result.message || 'Failed to remove passkey')
      }
    } catch (err: any) {
      alert('Failed to remove passkey: ' + (err.message || 'Unknown error'))
    }
  }

  const arrayBufferToBase64 = (buffer: ArrayBuffer): string => {
    const bytes = new Uint8Array(buffer)
    let binary = ''
    for (let i = 0; i < bytes.byteLength; i++) {
      binary += String.fromCharCode(bytes[i])
    }
    return btoa(binary)
  }

  const copyToClipboard = (text: string) => {
    navigator.clipboard.writeText(text)
    alert('Copied to clipboard!')
  }

  const downloadBackupCodes = () => {
    const blob = new Blob([backupCodes.join('\n')], { type: 'text/plain' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = 'backup-codes.txt'
    a.click()
    URL.revokeObjectURL(url)
  }

  return (
    <div>
      <h2 className="text-xl font-semibold text-foreground mb-4">
        <Shield className="w-5 h-5 inline mr-2" />
        Two-Factor Authentication
      </h2>

      <div className="bg-secondary/50 rounded-lg p-6 space-y-6">
        <p className="text-sm text-muted-foreground">
          Add an extra layer of security to your account by requiring a second form of authentication.
        </p>

        {/* TOTP Section */}
        <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
          <div className="flex items-center justify-between mb-3">
            <div className="flex items-center gap-3">
              <Smartphone className="w-5 h-5 text-slate-700 dark:text-slate-300" />
              <div>
                <h3 className="font-medium text-slate-900 dark:text-slate-100">
                  Authenticator App (TOTP)
                </h3>
                <p className="text-sm text-slate-600 dark:text-slate-400">
                  Use an app like Google Authenticator or Authy
                </p>
              </div>
            </div>
            <div className="flex items-center gap-2">
              {(twoFAStatus as any)?.totp?.enabled ? (
                <>
                  <span className="text-sm text-green-600 dark:text-green-400 font-medium">Enabled</span>
                  <button
                    onClick={handleDisableTOTP}
                    disabled={disableTOTPMutation.isPending}
                    className="px-3 py-1.5 bg-red-600 hover:bg-red-700 disabled:bg-slate-400 text-white text-sm rounded transition-colors"
                  >
                    Disable
                  </button>
                </>
              ) : (
                <button
                  onClick={handleEnableTOTP}
                  disabled={setupTOTPMutation.isPending}
                  className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white text-sm rounded transition-colors"
                >
                  {setupTOTPMutation.isPending ? 'Setting up...' : 'Enable'}
                </button>
              )}
            </div>
          </div>

          {/* TOTP Setup Modal */}
          {setupMethod === 'totp' && totpSetupData && (
            <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 space-y-4">
              <div className="text-center">
                <p className="text-sm text-slate-700 dark:text-slate-300 mb-3">
                  Scan this QR code with your authenticator app:
                </p>
                <div className="flex justify-center mb-3">
                  <img
                    src={totpSetupData.qrCodeDataURL}
                    alt="TOTP QR Code"
                    className="w-48 h-48 bg-white p-2 rounded-lg"
                  />
                </div>
                <p className="text-xs text-slate-600 dark:text-slate-400 mb-2">
                  Or enter this key manually:
                </p>
                <div className="flex items-center justify-center gap-2">
                  <code className="px-3 py-1 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded text-sm">
                    {totpSetupData.manualEntryKey}
                  </code>
                  <button
                    onClick={() => copyToClipboard(totpSetupData.manualEntryKey)}
                    className="p-1.5 hover:bg-blue-100 dark:hover:bg-blue-800 rounded transition-colors"
                  >
                    <Copy className="w-4 h-4 text-slate-600 dark:text-slate-400" />
                  </button>
                </div>
              </div>

              <div className="space-y-3">
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300">
                  Enter the 6-digit code from your app:
                </label>
                <input
                  type="text"
                  value={totpVerifyCode}
                  onChange={(e) => setTotpVerifyCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                  placeholder="000000"
                  maxLength={6}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-center text-lg tracking-widest"
                />
                <div className="flex gap-2">
                  <button
                    onClick={handleVerifyTOTP}
                    disabled={enableTOTPMutation.isPending || totpVerifyCode.length !== 6}
                    className="flex-1 px-4 py-2 bg-green-600 hover:bg-green-700 disabled:bg-slate-400 text-white rounded-lg transition-colors"
                  >
                    {enableTOTPMutation.isPending ? 'Verifying...' : 'Verify & Enable'}
                  </button>
                  <button
                    onClick={() => {
                      setSetupMethod(null)
                      setTotpSetupData(null)
                      setTotpVerifyCode('')
                    }}
                    className="px-4 py-2 bg-slate-200 hover:bg-slate-300 dark:bg-slate-700 dark:hover:bg-slate-600 text-slate-900 dark:text-slate-100 rounded-lg transition-colors"
                  >
                    Cancel
                  </button>
                </div>
              </div>
            </div>
          )}
        </div>

        {/* Passkey Section */}
        <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
              <Fingerprint className="w-5 h-5 text-slate-700 dark:text-slate-300" />
              <div>
                <h3 className="font-medium text-slate-900 dark:text-slate-100">
                  Passkeys (WebAuthn)
                </h3>
                <p className="text-sm text-slate-600 dark:text-slate-400">
                  Use Face ID, Touch ID, or hardware security keys
                </p>
              </div>
            </div>
            <div className="flex items-center gap-2">
              {(twoFAStatus as any)?.passkey?.available === false ? (
                <span className="text-sm text-slate-500 dark:text-slate-400 font-medium">
                  Unavailable - Library Compatibility Issue
                </span>
              ) : (twoFAStatus as any)?.passkey?.enabled ? (
                <>
                  <span className="text-sm text-green-600 dark:text-green-400 font-medium">
                    Enabled ({(twoFAStatus as any)?.passkey?.credentialCount || 0} passkeys)
                  </span>
                  <button
                    onClick={handleEnrollPasskey}
                    className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded transition-colors"
                  >
                    Add Passkey
                  </button>
                </>
              ) : (
                <button
                  onClick={handleEnrollPasskey}
                  className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded transition-colors"
                >
                  Enable
                </button>
              )}
            </div>
          </div>
          {(twoFAStatus as any)?.passkey?.available === false && (
            <div className="mt-3 bg-slate-50 dark:bg-slate-900/40 border border-slate-200 dark:border-slate-700 rounded p-3">
              <p className="text-xs text-slate-600 dark:text-slate-400">
                <strong>Note:</strong> Passkey support is temporarily disabled due to webauthn library compatibility issues.
                The implementation is ready and will automatically activate when the required library version becomes available.
              </p>
            </div>
          )}

          {/* Passkey Enrollment Modal */}
          {setupMethod === 'passkey' && (
            <div className="mt-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 space-y-4">
              <div>
                <h4 className="font-medium text-slate-900 dark:text-slate-100 mb-2">
                  Add a New Passkey
                </h4>
                <p className="text-sm text-slate-600 dark:text-slate-400 mb-3">
                  Give this passkey a name to help you identify it later (e.g., "MacBook Touch ID", "YubiKey", "iPhone")
                </p>
                <input
                  type="text"
                  value={passkeyName}
                  onChange={(e) => setPasskeyName(e.target.value)}
                  placeholder="Passkey name"
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 mb-3"
                />
                <div className="flex gap-2">
                  <button
                    onClick={handlePasskeyEnrollment}
                    disabled={enrollingPasskey || !passkeyName.trim()}
                    className="flex-1 px-4 py-2 bg-green-600 hover:bg-green-700 disabled:bg-slate-400 text-white rounded-lg transition-colors"
                  >
                    {enrollingPasskey ? 'Registering...' : 'Register Passkey'}
                  </button>
                  <button
                    onClick={() => {
                      setSetupMethod(null)
                      setPasskeyName('')
                    }}
                    disabled={enrollingPasskey}
                    className="px-4 py-2 bg-slate-200 hover:bg-slate-300 dark:bg-slate-700 dark:hover:bg-slate-600 text-slate-900 dark:text-slate-100 rounded-lg transition-colors"
                  >
                    Cancel
                  </button>
                </div>
              </div>
            </div>
          )}

          {/* Passkey List */}
          {(twoFAStatus as any)?.passkey?.enabled && (passkeyList as any)?.credentials?.length > 0 && (
            <div className="mt-3 space-y-2">
              <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300">Your Passkeys:</h4>
              {(passkeyList as any).credentials.map((passkey: any) => (
                <div
                  key={passkey.credentialId}
                  className="flex items-center justify-between bg-slate-50 dark:bg-slate-900/40 border border-slate-200 dark:border-slate-700 rounded-lg p-3"
                >
                  <div>
                    <p className="font-medium text-slate-900 dark:text-slate-100">{passkey.deviceName || 'Unnamed Device'}</p>
                    <p className="text-xs text-slate-600 dark:text-slate-400">
                      Added {new Date(passkey.createdAt).toLocaleDateString()}
                    </p>
                  </div>
                  <button
                    onClick={() => handleRemovePasskey(passkey.credentialId, passkey.deviceName || 'Unnamed Device')}
                    className="px-3 py-1.5 bg-red-600 hover:bg-red-700 text-white text-sm rounded transition-colors"
                  >
                    Remove
                  </button>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* Duo Section */}
        <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
              <Shield className="w-5 h-5 text-slate-700 dark:text-slate-300" />
              <div>
                <h3 className="font-medium text-slate-900 dark:text-slate-100">
                  Duo Security
                </h3>
                <p className="text-sm text-slate-600 dark:text-slate-400">
                  Use Duo push notifications or phone call
                </p>
              </div>
            </div>
            <div className="flex items-center gap-2">
              {(twoFAStatus as any)?.duo?.enabled ? (
                <>
                  <span className="text-sm text-green-600 dark:text-green-400 font-medium">Enabled</span>
                  <button
                    onClick={handleDisableDuo}
                    disabled={disableDuoMutation.isPending}
                    className="px-3 py-1.5 bg-red-600 hover:bg-red-700 disabled:bg-slate-400 text-white text-sm rounded transition-colors"
                  >
                    Disable
                  </button>
                </>
              ) : (
                <button
                  onClick={handleEnrollDuo}
                  disabled={enrollDuoMutation.isPending}
                  className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white text-sm rounded transition-colors"
                >
                  {enrollDuoMutation.isPending ? 'Enrolling...' : 'Enable'}
                </button>
              )}
            </div>
          </div>
        </div>

        {/* Backup Codes Display */}
        {backupCodes.length > 0 && (
          <div className="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4">
            <div className="flex items-start gap-3 mb-3">
              <Key className="w-5 h-5 text-yellow-600 dark:text-yellow-400 flex-shrink-0 mt-0.5" />
              <div className="flex-1">
                <h4 className="font-medium text-yellow-900 dark:text-yellow-100 mb-1">
                  Save Your Backup Codes
                </h4>
                <p className="text-sm text-yellow-800 dark:text-yellow-200 mb-3">
                  Store these codes in a safe place. You can use them to access your account if you lose your authenticator device.
                </p>
                <div className="grid grid-cols-2 gap-2 mb-3">
                  {backupCodes.map((code, idx) => (
                    <code key={idx} className="px-2 py-1 bg-white dark:bg-slate-800 border border-yellow-300 dark:border-yellow-700 rounded text-sm text-center">
                      {code}
                    </code>
                  ))}
                </div>
                <button
                  onClick={downloadBackupCodes}
                  className="px-3 py-1.5 bg-yellow-600 hover:bg-yellow-700 text-white text-sm rounded transition-colors flex items-center gap-2"
                >
                  <DownloadIcon className="w-4 h-4" />
                  Download Backup Codes
                </button>
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  )
}

function PlatformsTab() {
  type PlatformType = 'tiktok' | 'instagram_unified' | 'snapchat' | 'snapchat_client' | 'forums' | 'coppermine' | 'youtube_monitors'
  const [searchParams] = useSearchParams()
  const platformParam = searchParams.get('platform') as PlatformType | null
  const validPlatforms: PlatformType[] = ['tiktok', 'instagram_unified', 'snapchat', 'forums', 'coppermine', 'youtube_monitors']
  const [activePlatform, setActivePlatform] = useState<PlatformType>(
    platformParam && validPlatforms.includes(platformParam) ? platformParam : 'tiktok'
  )
  const [editedConfig, setEditedConfig] = useState<any>(null)
  const instagramUnifiedRef = useRef<InstagramUnifiedRef>(null)
  const queryClient = useQueryClient()

  const { data: config, isLoading } = useQuery({
    queryKey: ['config'],
    queryFn: () => api.getConfig(),
  })

  // Sync editedConfig with query data (initial load and after save/refetch)
  useEffect(() => {
    if (config) {
      setEditedConfig(config)
    }
  }, [config])

  const updateMutation = useMutation({
    mutationFn: (newConfig: any) => api.updateConfig(newConfig),
    onSuccess: () => {
      notificationManager.settingsSaved('Platform')
      queryClient.invalidateQueries({ queryKey: ['config'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Platform')
    },
  })

  const handleSave = () => {
    if (activePlatform === 'instagram_unified') {
      instagramUnifiedRef.current?.save()
      return
    }
    if (editedConfig) {
      updateMutation.mutate(editedConfig)
    }
  }

  const updatePlatform = (platform: string, updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      [platform]: {
        ...prev[platform],
        ...updates
      }
    }))
  }

  const updateNestedPlatformField = (platform: string, field: string, updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      [platform]: {
        ...prev[platform],
        [field]: {
          ...prev[platform]?.[field],
          ...updates
        }
      }
    }))
  }

  if (isLoading || !editedConfig) return <div className="flex items-center justify-center py-8"><div className="text-slate-600 dark:text-slate-400">Loading platform settings...</div></div>

  const tiktok = editedConfig.tiktok || {}
  const snapchat = editedConfig.snapchat || {}
  const snapchat_client = editedConfig.snapchat_client || {}
  const forums = editedConfig.forums || {}
  const coppermine = editedConfig.coppermine || {}
  const platformTabs = [
    { id: 'tiktok' as PlatformType, label: 'TikTok', icon: 'TT', bgColor: 'bg-black' },
    { id: 'instagram_unified' as PlatformType, label: 'Instagram', icon: 'IG', bgColor: 'bg-gradient-to-r from-purple-600 to-pink-600', neverHide: true },
    { id: 'snapchat' as PlatformType, label: 'Snapchat', icon: 'SC', bgColor: 'bg-yellow-400' },
    { id: 'snapchat_client' as PlatformType, label: 'Snapchat', icon: 'SC', bgColor: 'bg-gradient-to-r from-yellow-400 to-orange-500' },
    { id: 'forums' as PlatformType, label: 'Forums', icon: 'FR', bgColor: 'bg-green-600' },
    { id: 'coppermine' as PlatformType, label: 'Coppermine', icon: 'CP', bgColor: 'bg-orange-600' },
    { id: 'youtube_monitors' as PlatformType, label: 'YouTube', icon: 'YT', bgColor: 'bg-red-600' },
  ]

  const hiddenModules = editedConfig.hidden_modules || []
  const visiblePlatformTabs = platformTabs.filter(tab => (tab as any).neverHide || !hiddenModules.includes(tab.id))

  return (
    <div className="space-y-6">
      {/* Platform Tabs */}
      <div className="border-b border-slate-200 dark:border-slate-700">
        <div className="flex flex-wrap gap-2 pb-2">
          {visiblePlatformTabs.map((tab) => (
            <button
              key={tab.id}
              onClick={() => setActivePlatform(tab.id)}
              className={`
                flex items-center space-x-2 px-4 py-2 rounded-t-lg transition-all text-sm font-medium
                ${activePlatform === tab.id
                  ? 'bg-white dark:bg-slate-800 border-t border-x border-slate-200 dark:border-slate-700 text-blue-600 dark:text-blue-400 shadow-sm'
                  : 'bg-slate-50 dark:bg-slate-900 text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-200 hover:bg-slate-100 dark:hover:bg-slate-800'
                }
              `}
            >
              <div className={`w-6 h-6 ${tab.bgColor} rounded flex items-center justify-center text-white text-xs font-bold`}>
                {tab.icon}
              </div>
              <span>{tab.label}</span>
            </button>
          ))}
        </div>
      </div>

      {/* TIKTOK */}
      {activePlatform === 'tiktok' && (
      <div className="card-glass rounded-xl overflow-hidden">
        <div className="bg-gradient-to-r from-slate-50 to-slate-100 dark:from-slate-800 dark:to-slate-700 border-b border-slate-200 dark:border-slate-700 px-5 py-4 flex items-center justify-between">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-black rounded-lg flex items-center justify-center">
              <span className="text-white font-bold text-sm">TT</span>
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">TikTok</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Video content platform</p>
            </div>
          </div>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={tiktok.enabled || false}
              onChange={(e) => updatePlatform('tiktok', { enabled: e.target.checked })}
              className="w-4 h-4 rounded border-slate-300"
            />
            <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enabled</span>
          </label>
        </div>
        <div className="p-5 space-y-4">
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Days Back</label>
              <input
                type="number"
                min="1"
                value={tiktok.days_back || 3}
                onChange={(e) => updatePlatform('tiktok', { days_back: parseInt(e.target.value) || 3 })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-blue-500"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">How many days back to check for new content</p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Temp Directory</label>
              <input
                type="text"
                value={tiktok.temp_dir || ''}
                onChange={(e) => updatePlatform('tiktok', { temp_dir: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm focus:ring-2 focus:ring-blue-500"
                placeholder="temp/tiktok"
              />
            </div>
          </div>
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Destination Path</label>
            <input
              type="text"
              value={tiktok.destination_path || ''}
              onChange={(e) => updatePlatform('tiktok', { destination_path: e.target.value })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm focus:ring-2 focus:ring-blue-500"
              placeholder="/opt/immich/md/social media/tiktok/reels"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">Final destination for downloaded content</p>
          </div>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
            <div className="flex items-center space-x-2 p-3 bg-slate-50 dark:bg-slate-900 rounded-lg">
              <input
                type="checkbox"
                checked={tiktok.full_profile || false}
                onChange={(e) => updatePlatform('tiktok', { full_profile: e.target.checked })}
                className="w-4 h-4 rounded border-slate-300"
                id="tiktok-full-profile"
              />
              <label htmlFor="tiktok-full-profile" className="text-sm font-medium text-slate-700 dark:text-slate-300 cursor-pointer">
                Download full profile
              </label>
            </div>
            <div className="flex items-center space-x-2 p-3 bg-slate-50 dark:bg-slate-900 rounded-lg">
              <input
                type="checkbox"
                checked={tiktok.run_at_start || false}
                onChange={(e) => updatePlatform('tiktok', { run_at_start: e.target.checked })}
                className="w-4 h-4 rounded border-slate-300"
                id="tiktok-run-at-start"
              />
              <label htmlFor="tiktok-run-at-start" className="text-sm font-medium text-slate-700 dark:text-slate-300 cursor-pointer">
                Run at start
              </label>
            </div>
          </div>
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">File Extensions</label>
            <input
              type="text"
              value={tiktok.extensions?.join(', ') || ''}
              onChange={(e) => updatePlatform('tiktok', { extensions: e.target.value.split(',').map((ext: string) => ext.trim()).filter((ext: string) => ext) })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm focus:ring-2 focus:ring-blue-500"
              placeholder=".mp4, .webm, .m4a"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">Comma-separated list of file extensions to download</p>
          </div>
          <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Monitored Accounts</label>
            {tiktok.accounts && tiktok.accounts.length > 0 ? (
              <div className="space-y-3">
                {tiktok.accounts.map((account: any, idx: number) => (
                  <div key={idx} className="p-4 card-glass rounded-xl">
                    <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
                      <div>
                        <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Username</label>
                        <input
                          type="text"
                          value={account.username || ''}
                          onChange={(e) => {
                            const updated = [...tiktok.accounts]
                            updated[idx] = { ...updated[idx], username: e.target.value }
                            updatePlatform('tiktok', { accounts: updated })
                          }}
                          className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                          placeholder="username"
                        />
                      </div>
                      <div>
                        <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Check Interval (hours)</label>
                        <input
                          type="number"
                          min="1"
                          value={account.check_interval_hours || 4}
                          onChange={(e) => {
                            const updated = [...tiktok.accounts]
                            updated[idx] = { ...updated[idx], check_interval_hours: parseInt(e.target.value) || 4 }
                            updatePlatform('tiktok', { accounts: updated })
                          }}
                          className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                        />
                      </div>
                      <div className="flex items-end">
                        <label className="flex items-center space-x-2 cursor-pointer pb-2">
                          <input
                            type="checkbox"
                            checked={account.run_at_start || false}
                            onChange={(e) => {
                              const updated = [...tiktok.accounts]
                              updated[idx] = { ...updated[idx], run_at_start: e.target.checked }
                              updatePlatform('tiktok', { accounts: updated })
                            }}
                            className="w-4 h-4 rounded border-slate-300"
                          />
                          <span className="text-xs text-slate-600 dark:text-slate-400">Run at start</span>
                        </label>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className="text-sm text-slate-500 dark:text-slate-400 p-3 card-glass rounded-xl">
                No accounts configured. Edit database to add accounts.
              </div>
            )}
          </div>
        </div>
      </div>
      )}

      {/* INSTAGRAM (Unified) */}
      {activePlatform === 'instagram_unified' && (
        <InstagramUnified ref={instagramUnifiedRef} />
      )}

      {/* SNAPCHAT */}
      {activePlatform === 'snapchat' && (
      <div className="card-glass rounded-xl overflow-hidden">
        <div className="bg-gradient-to-r from-yellow-50 to-yellow-100 dark:from-yellow-900/20 dark:to-yellow-800/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4 flex items-center justify-between">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-yellow-400 rounded-lg flex items-center justify-center">
              <span className="text-slate-900 font-bold text-lg">👻</span>
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Snapchat (Direct)</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Direct scraper with highlight stitching</p>
            </div>
          </div>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={snapchat.enabled || false}
              onChange={(e) => updatePlatform('snapchat', { enabled: e.target.checked })}
              className="w-4 h-4 rounded border-slate-300"
            />
            <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enabled</span>
          </label>
        </div>
        <div className="p-5 space-y-4">
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Check Interval (hours)</label>
              <input
                type="number"
                min="1"
                value={snapchat.check_interval_hours || 4}
                onChange={(e) => updatePlatform('snapchat', { check_interval_hours: parseInt(e.target.value) || 4 })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-yellow-500"
              />
            </div>
            <div className="flex items-end">
              <label className="flex items-center space-x-2 p-3 bg-slate-50 dark:bg-slate-900 rounded-lg w-full cursor-pointer">
                <input
                  type="checkbox"
                  checked={snapchat.run_at_start || false}
                  onChange={(e) => updatePlatform('snapchat', { run_at_start: e.target.checked })}
                  className="w-4 h-4 rounded border-slate-300"
                  id="snapchat-run-at-start"
                />
                <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Run at start</span>
              </label>
            </div>
          </div>
          <UsernameListEditor
            value={snapchat.usernames || []}
            onChange={(usernames) => updatePlatform('snapchat', { usernames })}
            label="Usernames to Monitor"
            placeholder="Add Snapchat username..."
          />
          {/* Stories Settings */}
          <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Stories Settings</label>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Days Back</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat.stories?.days_back || 3}
                  onChange={(e) => updateNestedPlatformField('snapchat', 'stories', { days_back: parseInt(e.target.value) || 3 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Max Downloads</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat.stories?.max_downloads || 50}
                  onChange={(e) => updateNestedPlatformField('snapchat', 'stories', { max_downloads: parseInt(e.target.value) || 50 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
            </div>
            <div className="mt-3">
              <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Destination Path</label>
              <input
                type="text"
                value={snapchat.stories?.destination_path || ''}
                onChange={(e) => updateNestedPlatformField('snapchat', 'stories', { destination_path: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
                placeholder="/opt/immich/md/social media/snapchat/stories"
              />
            </div>
          </div>
          {/* Spotlight Settings */}
          <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Spotlight Settings</label>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Days Back</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat.spotlight?.days_back || 30}
                  onChange={(e) => updateNestedPlatformField('snapchat', 'spotlight', { days_back: parseInt(e.target.value) || 30 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Max Downloads</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat.spotlight?.max_downloads || 100}
                  onChange={(e) => updateNestedPlatformField('snapchat', 'spotlight', { max_downloads: parseInt(e.target.value) || 100 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
            </div>
            <div className="mt-3">
              <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Destination Path</label>
              <input
                type="text"
                value={snapchat.spotlight?.destination_path || ''}
                onChange={(e) => updateNestedPlatformField('snapchat', 'spotlight', { destination_path: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
                placeholder="/opt/immich/md/social media/snapchat/spotlight"
              />
            </div>
          </div>
        </div>
      </div>

      )}
      {/* SNAPCHAT CLIENT */}
      {activePlatform === 'snapchat_client' && (
      <div className="card-glass rounded-xl overflow-hidden">
        <div className="bg-gradient-to-r from-yellow-50 to-orange-100 dark:from-yellow-900/20 dark:to-orange-800/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4 flex items-center justify-between">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-r from-yellow-400 to-orange-500 rounded-lg flex items-center justify-center">
              <span className="text-white font-bold text-sm">SA</span>
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Snapchat Client (API)</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Direct HTTP scraper - no Playwright or Cloudflare</p>
            </div>
          </div>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={snapchat_client.enabled || false}
              onChange={(e) => updatePlatform('snapchat_client', { enabled: e.target.checked })}
              className="w-4 h-4 rounded border-slate-300"
            />
            <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enabled</span>
          </label>
        </div>
        <div className="p-5 space-y-4">
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Check Interval (hours)</label>
              <input
                type="number"
                min="1"
                value={snapchat_client.check_interval_hours || 6}
                onChange={(e) => updatePlatform('snapchat_client', { check_interval_hours: parseInt(e.target.value) || 6 })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-yellow-500"
              />
            </div>
            <div className="flex items-end">
              <label className="flex items-center space-x-2 p-3 bg-slate-50 dark:bg-slate-900 rounded-lg w-full cursor-pointer">
                <input
                  type="checkbox"
                  checked={snapchat_client.run_at_start || false}
                  onChange={(e) => updatePlatform('snapchat_client', { run_at_start: e.target.checked })}
                  className="w-4 h-4 rounded border-slate-300"
                />
                <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Run at start</span>
              </label>
            </div>
          </div>
          <UsernameListEditor
            value={snapchat_client.usernames || []}
            onChange={(usernames) => updatePlatform('snapchat_client', { usernames })}
            label="Usernames to Monitor"
            placeholder="Add Snapchat username..."
          />
          {/* Stories Settings */}
          <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
            <div className="flex items-center justify-between mb-3">
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300">Stories Settings</label>
              <label className="flex items-center space-x-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={snapchat_client.stories?.enabled !== false}
                  onChange={(e) => updateNestedPlatformField('snapchat_client', 'stories', { enabled: e.target.checked })}
                  className="w-4 h-4 rounded border-slate-300"
                />
                <span className="text-xs text-slate-600 dark:text-slate-400">Enabled</span>
              </label>
            </div>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Days Back</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat_client.stories?.days_back || 3}
                  onChange={(e) => updateNestedPlatformField('snapchat_client', 'stories', { days_back: parseInt(e.target.value) || 3 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Max Downloads</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat_client.stories?.max_downloads || 50}
                  onChange={(e) => updateNestedPlatformField('snapchat_client', 'stories', { max_downloads: parseInt(e.target.value) || 50 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
            </div>
            <div className="mt-3">
              <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Destination Path</label>
              <input
                type="text"
                value={snapchat_client.stories?.destination_path || ''}
                onChange={(e) => updateNestedPlatformField('snapchat_client', 'stories', { destination_path: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
                placeholder="/opt/immich/md/social media/snapchat/stories"
              />
            </div>
          </div>
          {/* Spotlight Settings */}
          <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Spotlight Settings</label>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Days Back</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat_client.spotlight?.days_back || 30}
                  onChange={(e) => updateNestedPlatformField('snapchat_client', 'spotlight', { days_back: parseInt(e.target.value) || 30 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
              <div>
                <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Max Downloads</label>
                <input
                  type="number"
                  min="1"
                  value={snapchat_client.spotlight?.max_downloads || 100}
                  onChange={(e) => updateNestedPlatformField('snapchat_client', 'spotlight', { max_downloads: parseInt(e.target.value) || 100 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
            </div>
            <div className="mt-3">
              <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Destination Path</label>
              <input
                type="text"
                value={snapchat_client.spotlight?.destination_path || ''}
                onChange={(e) => updateNestedPlatformField('snapchat_client', 'spotlight', { destination_path: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
                placeholder="/opt/immich/md/social media/snapchat/spotlight"
              />
            </div>
          </div>
        </div>
      </div>

      )}
      {/* FORUMS */}
      {activePlatform === 'forums' && (
      <div className="card-glass rounded-xl overflow-hidden">
        <div className="bg-gradient-to-r from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4 flex items-center justify-between">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-green-600 to-emerald-600 rounded-lg flex items-center justify-center">
              <span className="text-white font-bold text-sm">XF</span>
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Forums</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">XenForo forum scrapers</p>
            </div>
          </div>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={forums.enabled || false}
              onChange={(e) => updatePlatform('forums', { enabled: e.target.checked })}
              className="w-4 h-4 rounded border-slate-300"
            />
            <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enabled</span>
          </label>
        </div>
        <div className="p-5 space-y-4">
          <div className="flex items-center space-x-2 p-3 bg-slate-50 dark:bg-slate-900 rounded-lg">
            <input
              type="checkbox"
              checked={forums.headless || false}
              onChange={(e) => updatePlatform('forums', { headless: e.target.checked })}
              className="w-4 h-4 rounded border-slate-300"
              id="forums-headless"
            />
            <label htmlFor="forums-headless" className="text-sm font-medium text-slate-700 dark:text-slate-300 cursor-pointer">
              Run browser in headless mode
            </label>
          </div>
          <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Configured Forums</label>
            {forums.configs && forums.configs.length > 0 ? (
              <div className="space-y-3">
                {forums.configs.map((forum: any, index: number) => (
                  <div key={index} className="p-4 card-glass rounded-xl">
                    <div className="flex items-start justify-between mb-4">
                      <div className="flex-1">
                        <div className="flex items-center space-x-2">
                          <input
                            type="text"
                            value={forum.name || ''}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], name: e.target.value }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="font-semibold px-2 py-1 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                            placeholder="Forum Name"
                          />
                          <span className="px-2 py-0.5 bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 text-xs rounded">
                            {forum.forum_type || 'xenoforo'}
                          </span>
                        </div>
                      </div>
                      <div className="flex items-center space-x-2">
                        <label className="flex items-center space-x-2 cursor-pointer">
                          <input
                            type="checkbox"
                            checked={forum.enabled || false}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], enabled: e.target.checked }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-4 h-4 rounded border-slate-300"
                          />
                          <span className="text-xs font-medium text-slate-700 dark:text-slate-300">Active</span>
                        </label>
                        <button
                          onClick={() => {
                            if (confirm(`Remove forum "${forum.name}"?`)) {
                              const updated = forums.configs.filter((_: any, i: number) => i !== index)
                              updatePlatform('forums', { configs: updated })
                            }
                          }}
                          className="p-1.5 hover:bg-red-100 dark:hover:bg-red-900/20 rounded transition-colors"
                          title="Remove forum"
                        >
                          <Trash2 className="w-4 h-4 text-red-600 dark:text-red-400" />
                        </button>
                      </div>
                    </div>
                    <div className="space-y-3">
                      <div>
                        <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Forum URL</label>
                        <input
                          type="text"
                          value={forum.forum_url || ''}
                          onChange={(e) => {
                            const updated = [...forums.configs]
                            updated[index] = { ...updated[index], forum_url: e.target.value }
                            updatePlatform('forums', { configs: updated })
                          }}
                          className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-xs"
                          placeholder="https://forum.example.com"
                        />
                      </div>
                      <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <div>
                          <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Search Query</label>
                          <input
                            type="text"
                            value={forum.search_query || ''}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], search_query: e.target.value }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                            placeholder="Search term"
                          />
                        </div>
                        <div>
                          <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Login Username</label>
                          <input
                            type="text"
                            value={forum.username || ''}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], username: e.target.value }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                            placeholder="username"
                          />
                        </div>
                      </div>
                      <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <div>
                          <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Password</label>
                          <input
                            type="password"
                            value={forum.password || ''}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], password: e.target.value }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                            placeholder="••••••••"
                          />
                        </div>
                        <div>
                          <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Temp Directory</label>
                          <input
                            type="text"
                            value={forum.temp_dir || ''}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], temp_dir: e.target.value }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-xs"
                            placeholder="temp/forums/forum_name"
                          />
                        </div>
                      </div>
                      <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
                        <div>
                          <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Check Interval (hours)</label>
                          <input
                            type="number"
                            min="1"
                            value={forum.check_interval_hours || 4}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], check_interval_hours: parseInt(e.target.value) || 4 }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                          />
                        </div>
                        <div>
                          <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Newer Than (days)</label>
                          <input
                            type="number"
                            min="1"
                            value={forum.newer_than_days || 7}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], newer_than_days: parseInt(e.target.value) || 7 }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                          />
                        </div>
                        <div>
                          <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Auto Track (days)</label>
                          <input
                            type="number"
                            min="1"
                            value={forum.auto_track_days || 30}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], auto_track_days: parseInt(e.target.value) || 30 }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                          />
                        </div>
                      </div>
                      <div>
                        <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Destination Path</label>
                        <input
                          type="text"
                          value={forum.destination_path || ''}
                          onChange={(e) => {
                            const updated = [...forums.configs]
                            updated[index] = { ...updated[index], destination_path: e.target.value }
                            updatePlatform('forums', { configs: updated })
                          }}
                          className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-xs"
                          placeholder="/opt/immich/md/forums/ForumName"
                        />
                      </div>
                      <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
                        <label className="flex items-center space-x-2 cursor-pointer p-3 bg-slate-50 dark:bg-slate-900 rounded-lg">
                          <input
                            type="checkbox"
                            checked={forum.run_at_start || false}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], run_at_start: e.target.checked }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-4 h-4 rounded border-slate-300"
                          />
                          <span className="text-xs text-slate-600 dark:text-slate-400">Run at start</span>
                        </label>
                        <label className="flex items-center space-x-2 cursor-pointer p-3 bg-slate-50 dark:bg-slate-900 rounded-lg">
                          <input
                            type="checkbox"
                            checked={forum.external_only || false}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], external_only: e.target.checked }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-4 h-4 rounded border-slate-300"
                          />
                          <span className="text-xs text-slate-600 dark:text-slate-400">External only</span>
                        </label>
                        <label className="flex items-center space-x-2 cursor-pointer p-3 bg-slate-50 dark:bg-slate-900 rounded-lg">
                          <input
                            type="checkbox"
                            checked={forum.update_monitored || false}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], update_monitored: e.target.checked }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-4 h-4 rounded border-slate-300"
                          />
                          <span className="text-xs text-slate-600 dark:text-slate-400">Update monitored</span>
                        </label>
                        <label className="flex items-center space-x-2 cursor-pointer p-3 bg-amber-50 dark:bg-amber-900/20 rounded-lg border border-amber-200 dark:border-amber-800">
                          <input
                            type="checkbox"
                            checked={forum.cloudflare_enabled || false}
                            onChange={(e) => {
                              const updated = [...forums.configs]
                              updated[index] = { ...updated[index], cloudflare_enabled: e.target.checked }
                              updatePlatform('forums', { configs: updated })
                            }}
                            className="w-4 h-4 rounded border-slate-300"
                          />
                          <span className="text-xs text-amber-700 dark:text-amber-400">Cloudflare bypass</span>
                        </label>
                      </div>
                      <div className="border-t border-slate-200 dark:border-slate-700 pt-3 mt-3">
                        <div className="text-xs font-medium text-slate-700 dark:text-slate-300 mb-2">Monitor Threads Settings</div>
                        <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                          <div>
                            <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Check Hours</label>
                            <input
                              type="number"
                              min="1"
                              value={forum.monitor_threads_check_hours || 4}
                              onChange={(e) => {
                                const updated = [...forums.configs]
                                updated[index] = { ...updated[index], monitor_threads_check_hours: parseInt(e.target.value) || 4 }
                                updatePlatform('forums', { configs: updated })
                              }}
                              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                            />
                          </div>
                          <div className="flex items-end">
                            <label className="flex items-center space-x-2 cursor-pointer p-3 bg-slate-50 dark:bg-slate-900 rounded-lg w-full">
                              <input
                                type="checkbox"
                                checked={forum.monitor_threads_run_at_start || false}
                                onChange={(e) => {
                                  const updated = [...forums.configs]
                                  updated[index] = { ...updated[index], monitor_threads_run_at_start: e.target.checked }
                                  updatePlatform('forums', { configs: updated })
                                }}
                                className="w-4 h-4 rounded border-slate-300"
                              />
                              <span className="text-xs text-slate-600 dark:text-slate-400">Run at start</span>
                            </label>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className="text-sm text-slate-500 dark:text-slate-400 p-4 card-glass rounded-xl">
                No forums configured. Click "+ Add Forum" below to add your first forum.
              </div>
            )}
            <button
              onClick={() => {
                const newForum = {
                  name: 'New Forum',
                  enabled: false,
                  check_interval_hours: 4,
                  run_at_start: false,
                  forum_type: 'xenoforo',
                  forum_url: '',
                  search_query: '',
                  username: '',
                  password: '',
                  newer_than_days: 7,
                  auto_track_days: 30,
                  temp_dir: 'temp/forums/newforum',
                  destination_path: '/opt/immich/md/forums/NewForum',
                  external_only: true,
                  update_monitored: true,
                  cloudflare_enabled: false,
                  monitor_threads_check_hours: 4,
                  monitor_threads_run_at_start: true
                }
                const updated = [...(forums.configs || []), newForum]
                updatePlatform('forums', { configs: updated })
              }}
              className="mt-3 w-full px-4 py-2 bg-green-50 hover:bg-green-100 dark:bg-green-900/20 dark:hover:bg-green-900/30 border border-green-200 dark:border-green-800 text-green-700 dark:text-green-400 rounded-lg transition-colors text-sm font-medium"
            >
              + Add Forum
            </button>
          </div>
        </div>
      </div>

      )}
      {/* COPPERMINE */}
      {activePlatform === 'coppermine' && (
      <div className="card-glass rounded-xl overflow-hidden">
        <div className="bg-gradient-to-r from-orange-50 to-amber-50 dark:from-orange-900/20 dark:to-amber-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4 flex items-center justify-between">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-orange-600 to-amber-600 rounded-lg flex items-center justify-center">
              <span className="text-white font-bold text-sm">CP</span>
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Coppermine</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Photo gallery downloader</p>
            </div>
          </div>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={coppermine.enabled || false}
              onChange={(e) => updatePlatform('coppermine', { enabled: e.target.checked })}
              className="w-4 h-4 rounded border-slate-300"
            />
            <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enabled</span>
          </label>
        </div>
        <div className="p-5 space-y-4">
          <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Global Days Back</label>
              <input
                type="number"
                min="1"
                value={coppermine.days_back || 7}
                onChange={(e) => updatePlatform('coppermine', { days_back: parseInt(e.target.value) || 7 })}
                className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base focus:ring-2 focus:ring-blue-500"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">Default days back for all galleries</p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Check Interval (hours)</label>
              <input
                type="number"
                min="1"
                value={coppermine.check_interval_hours || 12}
                onChange={(e) => updatePlatform('coppermine', { check_interval_hours: parseInt(e.target.value) || 12 })}
                className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base focus:ring-2 focus:ring-blue-500"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">Default check interval for all galleries</p>
            </div>
            <div className="flex items-end">
              <label className="flex items-center gap-3 cursor-pointer p-3 bg-slate-50 dark:bg-slate-900 rounded-lg w-full touch-manipulation min-h-[44px]">
                <input
                  type="checkbox"
                  checked={coppermine.run_at_start || false}
                  onChange={(e) => updatePlatform('coppermine', { run_at_start: e.target.checked })}
                  className="w-5 h-5 rounded border-slate-300"
                />
                <span className="text-sm text-slate-700 dark:text-slate-300">Run at start</span>
              </label>
            </div>
          </div>
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Global Destination Path</label>
            <input
              type="text"
              value={coppermine.destination_path || ''}
              onChange={(e) => updatePlatform('coppermine', { destination_path: e.target.value })}
              className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-base focus:ring-2 focus:ring-blue-500"
              placeholder="/opt/immich/md/gallery/Coppermine"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">Default destination for all galleries</p>
          </div>
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Cookie File</label>
            <input
              type="text"
              value={coppermine.cookie_file || 'cookies/coppermine_cookies.json'}
              onChange={(e) => updatePlatform('coppermine', { cookie_file: e.target.value })}
              className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-base focus:ring-2 focus:ring-blue-500"
              placeholder="cookies/coppermine_cookies.json"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">Path to store authentication cookies</p>
          </div>

          <div className="border-t border-slate-200 dark:border-slate-700 pt-4">
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Configured Galleries</label>
            {coppermine.galleries && coppermine.galleries.length > 0 ? (
              <div className="space-y-3">
                {coppermine.galleries.map((gallery: any, index: number) => (
                  <div key={index} className="p-4 card-glass rounded-xl">
                    {/* Gallery header - mobile friendly */}
                    <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-3">
                      <div className="flex items-center gap-3 flex-1 min-w-0">
                        <input
                          type="text"
                          value={gallery.name || ''}
                          onChange={(e) => {
                            const updated = [...coppermine.galleries]
                            updated[index] = { ...updated[index], name: e.target.value }
                            updatePlatform('coppermine', { galleries: updated })
                          }}
                          className="font-semibold px-3 py-2.5 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base flex-1 min-w-0"
                          placeholder="Gallery Name"
                        />
                      </div>
                      <div className="flex items-center gap-2 shrink-0">
                        <label className="flex items-center gap-2 cursor-pointer p-2 touch-manipulation">
                          <input
                            type="checkbox"
                            checked={gallery.enabled !== false}
                            onChange={(e) => {
                              const updated = [...coppermine.galleries]
                              updated[index] = { ...updated[index], enabled: e.target.checked }
                              updatePlatform('coppermine', { galleries: updated })
                            }}
                            className="w-5 h-5 rounded border-slate-300"
                          />
                          <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Active</span>
                        </label>
                        <button
                          onClick={() => {
                            const updated = coppermine.galleries.filter((_: any, i: number) => i !== index)
                            updatePlatform('coppermine', { galleries: updated })
                          }}
                          className="p-2.5 text-red-600 hover:bg-red-100 dark:text-red-400 dark:hover:bg-red-900/20 rounded-lg touch-manipulation"
                        >
                          <Trash2 className="w-5 h-5" />
                        </button>
                      </div>
                    </div>
                    <div className="space-y-3">
                      <div>
                        <label className="block text-sm text-slate-600 dark:text-slate-400 mb-1">Gallery URL</label>
                        <input
                          type="text"
                          value={gallery.url || ''}
                          onChange={(e) => {
                            const updated = [...coppermine.galleries]
                            updated[index] = { ...updated[index], url: e.target.value }
                            updatePlatform('coppermine', { galleries: updated })
                          }}
                          className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-base"
                          placeholder="https://example.com/thumbnails.php?album=lastup&cat=123"
                        />
                      </div>
                      <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
                        <div>
                          <label className="block text-sm text-slate-600 dark:text-slate-400 mb-1">Days Back</label>
                          <input
                            type="number"
                            min="1"
                            value={gallery.days_back || 7}
                            onChange={(e) => {
                              const updated = [...coppermine.galleries]
                              updated[index] = { ...updated[index], days_back: parseInt(e.target.value) || 7 }
                              updatePlatform('coppermine', { galleries: updated })
                            }}
                            className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                          />
                        </div>
                        <div>
                          <label className="block text-sm text-slate-600 dark:text-slate-400 mb-1">Max Pages</label>
                          <input
                            type="number"
                            min="1"
                            value={gallery.max_pages || 5}
                            onChange={(e) => {
                              const updated = [...coppermine.galleries]
                              updated[index] = { ...updated[index], max_pages: parseInt(e.target.value) || 5 }
                              updatePlatform('coppermine', { galleries: updated })
                            }}
                            className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                          />
                        </div>
                        <div>
                          <label className="block text-sm text-slate-600 dark:text-slate-400 mb-1">Check Hours</label>
                          <input
                            type="number"
                            min="1"
                            value={gallery.check_interval_hours || 12}
                            onChange={(e) => {
                              const updated = [...coppermine.galleries]
                              updated[index] = { ...updated[index], check_interval_hours: parseInt(e.target.value) || 12 }
                              updatePlatform('coppermine', { galleries: updated })
                            }}
                            className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                          />
                        </div>
                        <div className="flex items-end">
                          <label className="flex items-center gap-2 cursor-pointer p-3 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg w-full touch-manipulation min-h-[44px]">
                            <input
                              type="checkbox"
                              checked={gallery.run_at_start || false}
                              onChange={(e) => {
                                const updated = [...coppermine.galleries]
                                updated[index] = { ...updated[index], run_at_start: e.target.checked }
                                updatePlatform('coppermine', { galleries: updated })
                              }}
                              className="w-5 h-5 rounded border-slate-300"
                            />
                            <span className="text-sm text-slate-600 dark:text-slate-400">Run at start</span>
                          </label>
                        </div>
                      </div>
                      <div>
                        <label className="block text-sm text-slate-600 dark:text-slate-400 mb-1">Destination Path (optional)</label>
                        <input
                          type="text"
                          value={gallery.destination_path || ''}
                          onChange={(e) => {
                            const updated = [...coppermine.galleries]
                            updated[index] = { ...updated[index], destination_path: e.target.value }
                            updatePlatform('coppermine', { galleries: updated })
                          }}
                          className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-base"
                          placeholder="Uses global path if empty"
                        />
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className="text-sm text-slate-500 dark:text-slate-400 p-4 card-glass rounded-xl">
                No galleries configured. Click "+ Add Gallery" below to add your first gallery.
              </div>
            )}
            <button
              onClick={() => {
                const newGallery = {
                  name: 'New Gallery',
                  url: '',
                  days_back: 7,
                  max_pages: 5,
                  check_interval_hours: 12,
                  enabled: true,
                  run_at_start: false
                }
                updatePlatform('coppermine', { galleries: [...(coppermine.galleries || []), newGallery] })
              }}
              className="mt-3 w-full px-4 py-3 bg-amber-50 hover:bg-amber-100 dark:bg-amber-900/20 dark:hover:bg-amber-900/30 border border-amber-200 dark:border-amber-800 text-amber-700 dark:text-amber-400 rounded-lg transition-colors text-base font-medium touch-manipulation"
            >
              + Add Gallery
            </button>
          </div>
        </div>
      </div>
      )}

      {/* YOUTUBE MONITORS */}
      {activePlatform === 'youtube_monitors' && (
        <YouTubeMonitorsSection />
      )}

      {activePlatform !== 'youtube_monitors' && (
        <div className="flex justify-end">
          <button
            onClick={handleSave}
            disabled={updateMutation.isPending || (activePlatform === 'instagram_unified' && instagramUnifiedRef.current?.isSaving)}
            className="px-6 py-3 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded-lg transition-colors flex items-center space-x-2 shadow-lg hover:shadow-xl font-medium"
          >
            <Save className="w-5 h-5" />
            <span>{(updateMutation.isPending || (activePlatform === 'instagram_unified' && instagramUnifiedRef.current?.isSaving)) ? 'Saving...' : 'Save Platform Settings'}</span>
          </button>
        </div>
      )}
    </div>
  )
}

// YouTube Monitors Section Component - Global Settings + Channel List
function YouTubeMonitorsSection() {
  const queryClient = useQueryClient()
  // Removed channel modal/management state - now handled in ChannelMonitors page
  // const [showChannelModal, setShowChannelModal] = useState(false)
  // const [editingChannel, setEditingChannel] = useState<any>(null)
  // const [showHistoryModal, setShowHistoryModal] = useState(false)
  // const [historyChannelId, setHistoryChannelId] = useState<number | null>(null)
  // const [channelSearch, setChannelSearch] = useState('')

  // Global settings form state
  const [settingsForm, setSettingsForm] = useState({
    phrases: '',
    check_interval_hours: 6,
    quality: 'best',
    enabled: true,
    auto_start_queue: false,
    notifications_enabled: true,
    auto_pause_threshold_months: 24,
    paused_check_interval_days: 14,
    max_results_per_phrase: 100
  })
  const [settingsChanged, setSettingsChanged] = useState(false)

  // Removed channel form state - now handled in ChannelMonitors page
  // const [channelForm, setChannelForm] = useState({
  //   channel_url: '',
  //   channel_name: '',
  //   enabled: true
  // })

  const { data: monitorsData, isLoading } = useQuery({
    queryKey: ['youtube-monitors'],
    queryFn: () => api.getYouTubeMonitors()
  })

  // Sync settings form with fetched data
  React.useEffect(() => {
    if (monitorsData?.settings) {
      setSettingsForm({
        phrases: monitorsData.settings.phrases?.join(', ') || '',
        check_interval_hours: monitorsData.settings.check_interval_hours || 6,
        quality: monitorsData.settings.quality || 'best',
        enabled: !!monitorsData.settings.enabled,
        auto_start_queue: !!monitorsData.settings.auto_start_queue,
        notifications_enabled: monitorsData.settings.notifications_enabled !== 0,
        auto_pause_threshold_months: (monitorsData.settings as any).auto_pause_threshold_months || 24,
        paused_check_interval_days: (monitorsData.settings as any).paused_check_interval_days || 14,
        max_results_per_phrase: (monitorsData.settings as any).max_results_per_phrase || 100
      })
      setSettingsChanged(false)
    }
  }, [monitorsData?.settings])

  // Removed history query - now handled in ChannelMonitors page
  // const { data: historyData } = useQuery({
  //   queryKey: ['youtube-channel-history', historyChannelId],
  //   queryFn: () => historyChannelId ? api.getYouTubeChannelHistory(historyChannelId) : null,
  //   enabled: !!historyChannelId
  // })

  // Settings mutations
  const updateSettingsMutation = useMutation({
    mutationFn: (data: any) => api.updateYouTubeMonitorSettings(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['youtube-monitors'] })
      notificationManager.settingsSaved('YouTube Monitor')
      setSettingsChanged(false)
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'YouTube Monitor')
    }
  })

  // Removed channel mutations - now handled in ChannelMonitors page
  // const addChannelMutation = useMutation({
  //   mutationFn: (data: any) => api.addYouTubeChannel(data),
  //   onSuccess: () => {
  //     queryClient.invalidateQueries({ queryKey: ['youtube-monitors'] })
  //     notificationManager.success('Channel Added', 'YouTube channel added successfully')
  //     setShowChannelModal(false)
  //     resetChannelForm()
  //   },
  //   onError: (err: any) => {
  //     notificationManager.error('Error', err.message || 'Failed to add channel')
  //   }
  // })

  // const updateChannelMutation = useMutation({
  //   mutationFn: ({ id, data }: { id: number, data: any }) => api.updateYouTubeChannel(id, data),
  //   onSuccess: () => {
  //     queryClient.invalidateQueries({ queryKey: ['youtube-monitors'] })
  //     notificationManager.success('Channel Updated', 'YouTube channel updated successfully')
  //     setShowChannelModal(false)
  //     setEditingChannel(null)
  //     resetChannelForm()
  //   },
  //   onError: (err: any) => {
  //     notificationManager.error('Error', err.message || 'Failed to update channel')
  //   }
  // })

  // const deleteChannelMutation = useMutation({
  //   mutationFn: (id: number) => api.deleteYouTubeChannel(id),
  //   onSuccess: () => {
  //     queryClient.invalidateQueries({ queryKey: ['youtube-monitors'] })
  //     notificationManager.success('Channel Deleted', 'YouTube channel removed')
  //   },
  //   onError: (err: any) => {
  //     notificationManager.error('Error', err.message || 'Failed to delete channel')
  //   }
  // })

  const checkAllMutation = useMutation({
    mutationFn: () => api.checkAllYouTubeChannels(),
    onSuccess: (data) => {
      notificationManager.syncStarted(data.message || 'YouTube channels')
    },
    onError: (err: unknown) => {
      notificationManager.syncError('YouTube channels', err)
    }
  })

  // Removed individual channel check mutation - now handled in ChannelMonitors page
  // const checkChannelMutation = useMutation({
  //   mutationFn: (id: number) => api.checkYouTubeChannel(id),
  //   onSuccess: (data) => {
  //     notificationManager.success('Check Started', `Checking ${data.channel_name}...`)
  //   },
  //   onError: (err: any) => {
  //     notificationManager.error('Error', err.message || 'Failed to trigger check')
  //   }
  // })

  // Removed channel form helpers - now handled in ChannelMonitors page
  // const resetChannelForm = () => {
  //   setChannelForm({
  //     channel_url: '',
  //     channel_name: '',
  //     enabled: true
  //   })
  // }

  // const openEditChannelModal = (channel: any) => {
  //   setEditingChannel(channel)
  //   setChannelForm({
  //     channel_url: channel.channel_url,
  //     channel_name: channel.channel_name || '',
  //     enabled: !!channel.enabled
  //   })
  //   setShowChannelModal(true)
  // }

  const handleSaveSettings = () => {
    const phrases = settingsForm.phrases.split(',').map(p => p.trim()).filter(p => p)
    updateSettingsMutation.mutate({
      phrases,
      check_interval_hours: settingsForm.check_interval_hours,
      quality: settingsForm.quality,
      enabled: settingsForm.enabled,
      auto_start_queue: settingsForm.auto_start_queue,
      notifications_enabled: settingsForm.notifications_enabled,
      auto_pause_threshold_months: settingsForm.auto_pause_threshold_months,
      paused_check_interval_days: settingsForm.paused_check_interval_days,
      max_results_per_phrase: settingsForm.max_results_per_phrase
    })
  }

  // Removed channel submit handler - now handled in ChannelMonitors page
  // const handleChannelSubmit = () => {
  //   if (!channelForm.channel_url) {
  //     notificationManager.error('Validation Error', 'Channel URL is required')
  //     return
  //   }
  //
  //   const data = {
  //     channel_url: channelForm.channel_url,
  //     channel_name: channelForm.channel_name || undefined,
  //     enabled: channelForm.enabled
  //   }
  //
  //   if (editingChannel) {
  //     updateChannelMutation.mutate({ id: editingChannel.id, data })
  //   } else {
  //     addChannelMutation.mutate(data)
  //   }
  // }

  const settings = monitorsData?.settings

  // Removed channels sorting/filtering - now handled in ChannelMonitors page
  // const channels = React.useMemo(() => {
  //   const allChannels = monitorsData?.channels || []
  //   const sorted = [...allChannels].sort((a: any, b: any) => {
  //     const nameA = (a.channel_name || a.channel_url || '').toLowerCase()
  //     const nameB = (b.channel_name || b.channel_url || '').toLowerCase()
  //     return nameA.localeCompare(nameB)
  //   })
  //   if (!channelSearch.trim()) return sorted
  //   const search = channelSearch.toLowerCase()
  //   return sorted.filter((c: any) =>
  //     (c.channel_name || '').toLowerCase().includes(search) ||
  //     (c.channel_url || '').toLowerCase().includes(search)
  //   )
  // }, [monitorsData?.channels, channelSearch])

  return (
    <div className="card-glass rounded-xl overflow-hidden">
      {/* Header */}
      <div className="bg-gradient-to-r from-red-50 to-rose-50 dark:from-red-900/20 dark:to-rose-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4 flex items-center justify-between">
        <div className="flex items-center space-x-3">
          <div className="w-10 h-10 bg-gradient-to-br from-red-600 to-rose-600 rounded-lg flex items-center justify-center">
            <span className="text-white font-bold text-sm">YT</span>
          </div>
          <div>
            <h3 className="font-semibold text-slate-900 dark:text-slate-100">YouTube Monitors</h3>
            <p className="text-xs text-slate-500 dark:text-slate-400">Monitor channels for videos matching phrases</p>
          </div>
        </div>
        <div className="flex items-center space-x-2">
          <button
            onClick={() => checkAllMutation.mutate()}
            disabled={checkAllMutation.isPending || !monitorsData?.channels?.length}
            className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded-lg transition-colors text-sm font-medium flex items-center space-x-2"
          >
            <RefreshCcw className={`w-4 h-4 ${checkAllMutation.isPending ? 'animate-spin' : ''}`} />
            <span>Check All Now</span>
          </button>
        </div>
      </div>

      <div className="p-5 space-y-4">
        {isLoading ? (
          <div className="text-center py-8 text-slate-500">Loading...</div>
        ) : (
          <>
            {/* Global Settings Section */}
            <div className="p-4 border-b border-slate-200 dark:border-slate-700">
              <h4 className="text-sm font-semibold text-slate-900 dark:text-slate-100 mb-4 flex items-center gap-2">
                <Settings className="w-4 h-4" />
                Global Settings
              </h4>
              <div className="space-y-4">
                <div>
                  <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                    Match Phrases (comma-separated)
                  </label>
                  <input
                    type="text"
                    value={settingsForm.phrases}
                    onChange={(e) => { setSettingsForm({ ...settingsForm, phrases: e.target.value }); setSettingsChanged(true); }}
                    placeholder="interview, behind the scenes, exclusive, vlog"
                    className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                  />
                  <p className="text-xs text-slate-500 mt-1">
                    Videos from ALL monitored channels with titles/descriptions matching these phrases will be added to the download queue
                  </p>
                </div>
                <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
                  <div>
                    <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                      Check Interval
                    </label>
                    <select
                      value={settingsForm.check_interval_hours}
                      onChange={(e) => { setSettingsForm({ ...settingsForm, check_interval_hours: parseInt(e.target.value) }); setSettingsChanged(true); }}
                      className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                    >
                      <option value={1}>Every 1 hour</option>
                      <option value={3}>Every 3 hours</option>
                      <option value={6}>Every 6 hours</option>
                      <option value={12}>Every 12 hours</option>
                      <option value={24}>Every 24 hours</option>
                    </select>
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                      Quality
                    </label>
                    <select
                      value={settingsForm.quality}
                      onChange={(e) => { setSettingsForm({ ...settingsForm, quality: e.target.value }); setSettingsChanged(true); }}
                      className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                    >
                      <option value="best">Best</option>
                      <option value="1080p">1080p</option>
                      <option value="720p">720p</option>
                      <option value="480p">480p</option>
                    </select>
                  </div>
                  <div className="flex items-end">
                    <label className="flex items-center gap-3 cursor-pointer p-3 bg-slate-50 dark:bg-slate-900 rounded-lg w-full touch-manipulation min-h-[44px]">
                      <input
                        type="checkbox"
                        checked={settingsForm.enabled}
                        onChange={(e) => { setSettingsForm({ ...settingsForm, enabled: e.target.checked }); setSettingsChanged(true); }}
                        className="w-5 h-5 rounded border-slate-300"
                      />
                      <span className="text-sm text-slate-700 dark:text-slate-300">Enabled</span>
                    </label>
                  </div>
                </div>
                <div className="mt-4 p-3 bg-slate-50 dark:bg-slate-900 rounded-lg border border-slate-200 dark:border-slate-700 space-y-3">
                  <label className="flex items-start gap-3 cursor-pointer touch-manipulation min-h-[44px]">
                    <input
                      type="checkbox"
                      checked={settingsForm.auto_start_queue}
                      onChange={(e) => { setSettingsForm({ ...settingsForm, auto_start_queue: e.target.checked }); setSettingsChanged(true); }}
                      className="w-5 h-5 rounded border-slate-300 mt-0.5 shrink-0"
                    />
                    <div>
                      <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Auto-start download queue</span>
                      <p className="text-xs text-slate-500 dark:text-slate-400">Automatically start downloading when new videos are added to the queue</p>
                    </div>
                  </label>
                  <label className="flex items-start gap-3 cursor-pointer touch-manipulation min-h-[44px]">
                    <input
                      type="checkbox"
                      checked={settingsForm.notifications_enabled}
                      onChange={(e) => { setSettingsForm({ ...settingsForm, notifications_enabled: e.target.checked }); setSettingsChanged(true); }}
                      className="w-5 h-5 rounded border-slate-300 mt-0.5 shrink-0"
                    />
                    <div>
                      <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Send notifications</span>
                      <p className="text-xs text-slate-500 dark:text-slate-400">Send a push notification when new videos are added by scheduled checks</p>
                    </div>
                  </label>
                </div>
                <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mt-4">
                  <div>
                    <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                      Auto-Pause Threshold
                    </label>
                    <select
                      value={settingsForm.auto_pause_threshold_months}
                      onChange={(e) => { setSettingsForm({ ...settingsForm, auto_pause_threshold_months: parseInt(e.target.value) }); setSettingsChanged(true); }}
                      className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                    >
                      <option value={6}>6 months</option>
                      <option value={12}>12 months (1 year)</option>
                      <option value={18}>18 months</option>
                      <option value={24}>24 months (2 years)</option>
                      <option value={36}>36 months (3 years)</option>
                    </select>
                    <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
                      Automatically pause channels with no uploads for this period
                    </p>
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                      Paused Re-check Interval
                    </label>
                    <select
                      value={settingsForm.paused_check_interval_days}
                      onChange={(e) => { setSettingsForm({ ...settingsForm, paused_check_interval_days: parseInt(e.target.value) }); setSettingsChanged(true); }}
                      className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                    >
                      <option value={7}>7 days (weekly)</option>
                      <option value={14}>14 days (bi-weekly)</option>
                      <option value={30}>30 days (monthly)</option>
                    </select>
                    <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
                      How often to check paused channels for new uploads
                    </p>
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                      Max Results Per Phrase
                    </label>
                    <input
                      type="number"
                      min="10"
                      max="1000"
                      value={settingsForm.max_results_per_phrase}
                      onChange={(e) => { setSettingsForm({ ...settingsForm, max_results_per_phrase: parseInt(e.target.value) }); setSettingsChanged(true); }}
                      className="w-full px-3 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 text-base"
                    />
                    <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
                      Maximum number of matching videos to process per search phrase per channel
                    </p>
                  </div>
                </div>
                {settingsChanged && (
                  <div className="flex justify-end">
                    <button
                      onClick={handleSaveSettings}
                      disabled={updateSettingsMutation.isPending}
                      className="px-4 py-2.5 bg-green-600 hover:bg-green-700 disabled:bg-slate-400 text-white rounded-lg text-sm font-medium flex items-center gap-2 touch-manipulation"
                    >
                      <Save className="w-4 h-4" />
                      Save Settings
                    </button>
                  </div>
                )}
                {settings?.last_checked && (
                  <div className="text-xs text-slate-500">
                    Last checked all channels: {new Date(settings.last_checked).toLocaleString()}
                  </div>
                )}
              </div>
            </div>

            {/* Channel Management Section */}
            <div className="p-4 bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900/50 dark:to-slate-800/50">
              <div className="max-w-2xl mx-auto text-center py-8">
                <div className="mb-4">
                  <Layers className="w-12 h-12 mx-auto text-blue-600 dark:text-blue-400 mb-3" />
                  <h4 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">
                    Channel Monitoring
                  </h4>
                  <p className="text-sm text-slate-600 dark:text-slate-400 mb-6">
                    Channel monitoring has moved to its own dedicated page for better management, including auto-pause for inactive channels, bulk actions, and detailed statistics.
                  </p>
                </div>
                <Link
                  to="/video/channel-monitors"
                  className="inline-flex items-center gap-2 px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors touch-manipulation"
                >
                  <Layers className="w-5 h-5" />
                  Manage Channels
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                  </svg>
                </Link>
                {monitorsData?.channels && (
                  <div className="mt-4 text-sm text-slate-500 dark:text-slate-400">
                    {monitorsData.channels.length} channel{monitorsData.channels.length !== 1 ? 's' : ''} configured
                  </div>
                )}
              </div>
            </div>
          </>
        )}
      </div>

    </div>
  )
}

function SourceToleranceManager({ sourceTolerances, onUpdate }: { sourceTolerances: Record<string, number>, onUpdate: (newTolerances: Record<string, number>) => void }) {
  const [newSource, setNewSource] = useState('')
  const [newTolerance, setNewTolerance] = useState(0.25)

  const addSource = () => {
    if (newSource && !sourceTolerances[newSource]) {
      onUpdate({ ...sourceTolerances, [newSource]: newTolerance })
      setNewSource('')
      setNewTolerance(0.25)
    }
  }

  const updateSource = (source: string, tolerance: number) => {
    onUpdate({ ...sourceTolerances, [source]: tolerance })
  }

  const removeSource = (source: string) => {
    const { [source]: removed, ...rest } = sourceTolerances
    onUpdate(rest)
  }

  const getConfidencePercentage = (tolerance: number) => {
    return ((1 - tolerance) * 100).toFixed(0)
  }

  return (
    <div className="space-y-3">
      {/* Existing Sources */}
      {Object.entries(sourceTolerances).length > 0 ? (
        <div className="space-y-2">
          {Object.entries(sourceTolerances).map(([source, tolerance]) => (
            <div key={source} className="flex items-center gap-3 p-3 bg-slate-50 dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700">
              <div className="flex-1">
                <div className="font-medium text-sm text-slate-900 dark:text-slate-100">{source}</div>
                <div className="text-xs text-slate-500 dark:text-slate-400">≥{getConfidencePercentage(tolerance)}% confidence required</div>
              </div>
              <input
                type="number"
                step="0.05"
                min="0"
                max="1"
                value={tolerance}
                onChange={(e) => updateSource(source, parseFloat(e.target.value))}
                className="w-20 px-2 py-1 text-sm border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <button
                onClick={() => removeSource(source)}
                className="px-2 py-1 text-xs text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded"
              >
                Remove
              </button>
            </div>
          ))}
        </div>
      ) : (
        <div className="text-xs text-slate-500 dark:text-slate-400 italic">No source-specific tolerances configured. Default tolerance will be used for all sources.</div>
      )}

      {/* Add New Source */}
      <div className="pt-3 border-t border-slate-200 dark:border-slate-700">
        <div className="flex items-end gap-2">
          <div className="flex-1">
            <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Source Name</label>
            <input
              type="text"
              value={newSource}
              onChange={(e) => setNewSource(e.target.value)}
              placeholder="e.g., evalongoria, kenpaves"
              className="w-full px-3 py-2 text-sm border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              onKeyPress={(e) => e.key === 'Enter' && addSource()}
            />
          </div>
          <div className="w-24">
            <label className="block text-xs text-slate-600 dark:text-slate-400 mb-1">Tolerance</label>
            <input
              type="number"
              step="0.05"
              min="0"
              max="1"
              value={newTolerance}
              onChange={(e) => setNewTolerance(parseFloat(e.target.value))}
              className="w-full px-2 py-2 text-sm border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
            />
          </div>
          <button
            onClick={addSource}
            disabled={!newSource || (newSource in sourceTolerances)}
            className="px-4 py-2 text-sm bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 disabled:cursor-not-allowed text-white rounded transition-colors"
          >
            Add
          </button>
        </div>
        <p className="mt-2 text-xs text-slate-500 dark:text-slate-400">
          Add Instagram usernames or other source identifiers with custom tolerance levels. Higher tolerance = more relaxed matching.
        </p>
      </div>

      {/* Examples */}
      <div className="p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg">
        <h5 className="text-xs font-medium text-amber-900 dark:text-amber-100 mb-1">Examples</h5>
        <ul className="text-xs text-amber-700 dark:text-amber-300 space-y-1">
          <li>• <strong>evalongoria (0.30)</strong> - Her own account, accept ≥70% confidence</li>
          <li>• <strong>kenpaves (0.25)</strong> - Her stylist, accept ≥75% confidence</li>
          <li>• <strong>Default (0.20)</strong> - Unknown sources, require ≥80% confidence</li>
        </ul>
      </div>
    </div>
  )
}

function ReferenceStatsSection() {
  const { data: stats, isLoading, error } = useQuery({
    queryKey: ['faceReferenceStats'],
    queryFn: () => api.getFaceReferenceStats(),
    refetchInterval: 30000, // Refresh every 30 seconds
  })

  if (isLoading) {
    return (
      <div className="mt-4 p-4 bg-slate-50 dark:bg-slate-900/50 rounded-lg border border-slate-200 dark:border-slate-700">
        <p className="text-sm text-slate-600 dark:text-slate-400">Loading reference statistics...</p>
      </div>
    )
  }

  if (error) {
    return (
      <div className="mt-4 p-4 bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-200 dark:border-red-800">
        <p className="text-sm text-red-700 dark:text-red-300">Error loading reference statistics: {(error as Error).message}</p>
      </div>
    )
  }

  if (!stats || stats.total === 0) {
    return (
      <div className="mt-4 p-4 bg-slate-50 dark:bg-slate-900/50 rounded-lg border border-slate-200 dark:border-slate-700">
        <p className="text-sm text-slate-600 dark:text-slate-400">No reference faces found. Add reference faces from the Review or Media pages.</p>
      </div>
    )
  }

  return (
    <div className="mt-4 p-4 bg-slate-50 dark:bg-slate-900/50 rounded-lg border border-slate-200 dark:border-slate-700">
      <h4 className="text-sm font-semibold text-slate-900 dark:text-slate-100 mb-3 flex items-center gap-2">
        <Fingerprint className="w-4 h-4" />
        Reference Faces
      </h4>
      <div className="space-y-2">
        <div className="flex items-center justify-between text-sm">
          <span className="text-slate-600 dark:text-slate-400">Total References:</span>
          <span className="font-semibold text-slate-900 dark:text-slate-100">{stats.total}</span>
        </div>
        {Object.entries(stats.by_person).map(([personName, personStats]) => (
          <div key={personName} className="pt-2 border-t border-slate-200 dark:border-slate-700">
            <div className="flex items-center justify-between text-sm mb-1">
              <span className="font-medium text-slate-900 dark:text-slate-100">{personName}</span>
              <span className="text-slate-600 dark:text-slate-400">{personStats.count} references</span>
            </div>
            <div className="text-xs text-slate-500 dark:text-slate-400 space-y-0.5">
              <div>First added: {new Date(personStats.first_added).toLocaleDateString()}</div>
              <div>Last added: {new Date(personStats.last_added).toLocaleDateString()}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  )
}

function ReferenceManagementSection({ personName }: { personName: string }) {
  const queryClient = useQueryClient()
  const [selectedImagePath, setSelectedImagePath] = useState<string>('')

  const { data, isLoading, error } = useQuery({
    queryKey: ['faceReferences'],
    queryFn: () => api.getFaceReferences(),
    refetchInterval: 10000, // Refresh every 10 seconds
  })

  const deleteMutation = useMutation({
    mutationFn: (referenceId: number) => api.deleteFaceReference(referenceId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['faceReferences'] })
      queryClient.invalidateQueries({ queryKey: ['faceReferenceStats'] })
    },
  })

  const addMutation = useMutation({
    mutationFn: (data: { filePath: string, personName: string }) =>
      api.addFaceReferenceFromPath(data.filePath, data.personName),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['faceReferences'] })
      queryClient.invalidateQueries({ queryKey: ['faceReferenceStats'] })
      setSelectedImagePath('')
    },
  })

  const handleDelete = (referenceId: number) => {
    if (confirm('Are you sure you want to delete this reference face?')) {
      deleteMutation.mutate(referenceId)
    }
  }

  const handleAdd = () => {
    if (!selectedImagePath) {
      alert('Please enter an image path')
      return
    }
    addMutation.mutate({ filePath: selectedImagePath, personName })
  }

  if (isLoading) {
    return (
      <div className="p-4 bg-slate-50 dark:bg-slate-900/50 rounded-lg border border-slate-200 dark:border-slate-700">
        <p className="text-sm text-slate-600 dark:text-slate-400">Loading reference faces...</p>
      </div>
    )
  }

  if (error) {
    return (
      <div className="p-4 bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-200 dark:border-red-800">
        <p className="text-sm text-red-700 dark:text-red-300">Error loading references: {(error as Error).message}</p>
      </div>
    )
  }

  const references = data?.references || []

  return (
    <div className="space-y-4">
      {/* Add New Reference */}
      <div className="p-4 bg-slate-50 dark:bg-slate-900/50 rounded-lg border border-slate-200 dark:border-slate-700">
        <h5 className="text-sm font-medium text-slate-900 dark:text-slate-100 mb-2">Add New Reference</h5>
        <div className="flex gap-2">
          <input
            type="text"
            value={selectedImagePath}
            onChange={(e) => setSelectedImagePath(e.target.value)}
            placeholder="Enter full path to image file..."
            className="flex-1 px-3 py-2 text-sm border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
          />
          <button
            onClick={handleAdd}
            disabled={addMutation.isPending || !selectedImagePath}
            className="px-4 py-2 text-sm bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded"
          >
            {addMutation.isPending ? 'Adding...' : 'Add'}
          </button>
        </div>
        {addMutation.isError && (
          <p className="mt-2 text-xs text-red-600 dark:text-red-400">
            Error: {(addMutation.error as Error).message}
          </p>
        )}
        {addMutation.isSuccess && (
          <p className="mt-2 text-xs text-green-600 dark:text-green-400">
            Reference face added successfully!
          </p>
        )}
      </div>

      {/* Reference Faces Grid */}
      <div className="p-4 bg-slate-50 dark:bg-slate-900/50 rounded-lg border border-slate-200 dark:border-slate-700">
        <h5 className="text-sm font-medium text-slate-900 dark:text-slate-100 mb-3">
          Current References ({references.length})
        </h5>
        {references.length === 0 ? (
          <p className="text-sm text-slate-600 dark:text-slate-400">No reference faces yet. Add one above to get started.</p>
        ) : (
          <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
            {references.map((ref) => (
              <div key={ref.id} className="relative group">
                <div className="aspect-square rounded-lg overflow-hidden bg-slate-200 dark:bg-slate-800 border border-slate-300 dark:border-slate-600">
                  {ref.thumbnail ? (
                    <img
                      src={`data:image/jpeg;base64,${ref.thumbnail}`}
                      alt={`Reference ${ref.id}`}
                      className="w-full h-full object-cover"
                    />
                  ) : (
                    <div className="w-full h-full flex items-center justify-center text-slate-400">
                      No Image
                    </div>
                  )}
                </div>
                <button
                  onClick={() => handleDelete(ref.id)}
                  disabled={deleteMutation.isPending}
                  className="absolute top-1 right-1 p-1.5 bg-red-600 hover:bg-red-700 text-white rounded opacity-0 group-hover:opacity-100 transition-opacity"
                  title="Delete reference"
                >
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                  </svg>
                </button>
                <div className="mt-1 text-xs text-slate-600 dark:text-slate-400 truncate" title={ref.reference_image_path}>
                  Added: {new Date(ref.created_at).toLocaleDateString()}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  )
}

function InsightFaceModelSelector({ currentModel, onModelChange }: { currentModel: string, onModelChange: (model: string) => void }) {
  const [isChanging, setIsChanging] = useState(false)
  const [showConfirm, setShowConfirm] = useState(false)
  const [selectedModel, setSelectedModel] = useState(currentModel)
  const [retrainStatus, setRetrainStatus] = useState<string>('')
  const [progress, setProgress] = useState(0)
  const [elapsedTime, setElapsedTime] = useState(0)
  const [currentPerson, setCurrentPerson] = useState<string>('')
  const [currentCount, setCurrentCount] = useState(0)
  const [totalCount, setTotalCount] = useState(0)
  const startTimeRef = useRef<number | null>(null)

  const models = [
    { value: 'buffalo_l', label: 'Buffalo L (Recommended)', desc: '326MB - Best balance of accuracy & speed', size: '326MB' },
    { value: 'antelopev2', label: 'Antelopev2 (Highest Accuracy)', desc: '407MB - Most accurate, slightly slower', size: '407MB' },
    { value: 'buffalo_m', label: 'Buffalo M (Faster)', desc: '313MB - 4x faster detection, good accuracy', size: '313MB' },
    { value: 'buffalo_s', label: 'Buffalo S (Lightweight)', desc: '159MB - Lower resources, reduced accuracy', size: '159MB' },
    { value: 'buffalo_sc', label: 'Buffalo SC (Minimal)', desc: '16MB - Smallest size, basic features only', size: '16MB' }
  ]

  // Check for ongoing retraining on mount
  useEffect(() => {
    let pollInterval: ReturnType<typeof setInterval> | null = null
    let timerInterval: ReturnType<typeof setInterval> | null = null

    const checkForOngoingRetrain = async () => {
      try {
        const progress = await api.getRetrainProgress()
        if (progress.in_progress) {
          // Retraining is in progress - resume showing it
          setIsChanging(true)
          startTimeRef.current = Date.now()
          setCurrentCount(progress.current)
          setTotalCount(progress.total)
          setCurrentPerson(progress.person_name)
          setProgress(Math.round((progress.current / progress.total) * 100))
          setRetrainStatus(`Processing ${progress.person_name} (${progress.current}/${progress.total})`)

          // Start elapsed time counter
          timerInterval = setInterval(() => {
            if (startTimeRef.current) {
              setElapsedTime(Math.floor((Date.now() - startTimeRef.current) / 1000))
            }
          }, 500)

          // Continue polling for updates
          pollInterval = setInterval(async () => {
            try {
              const newProgress = await api.getRetrainProgress()
              if (newProgress.in_progress) {
                setCurrentCount(newProgress.current)
                setTotalCount(newProgress.total)
                setCurrentPerson(newProgress.person_name)
                setProgress(Math.round((newProgress.current / newProgress.total) * 100))
                setRetrainStatus(`Processing ${newProgress.person_name} (${newProgress.current}/${newProgress.total})`)
              } else {
                // Retraining finished
                setIsChanging(false)
                setProgress(100)
                setRetrainStatus(`✓ Re-training complete`)
                if (pollInterval) clearInterval(pollInterval)
                if (timerInterval) clearInterval(timerInterval)
                setTimeout(() => {
                  setRetrainStatus('')
                  setProgress(0)
                }, 5000)
              }
            } catch (e) {
              console.error('Failed to check retrain progress:', e)
            }
          }, 500)
        }
      } catch (e) {
        console.error('Failed to check initial retrain status:', e)
      }
    }

    checkForOngoingRetrain()

    return () => {
      if (pollInterval) clearInterval(pollInterval)
      if (timerInterval) clearInterval(timerInterval)
    }
  }, [])

  // Listen for WebSocket progress updates
  useEffect(() => {
    // Ensure WebSocket is connected
    wsClient.connect()

    const unsubscribe = wsClient.on('face_retrain_progress', (data: any) => {
      setIsChanging(true)
      setCurrentCount(data.current)
      setTotalCount(data.total)
      setCurrentPerson(data.person_name)
      setProgress(data.percentage)
      setRetrainStatus(`Processing ${data.person_name} (${data.current}/${data.total})`)
    })

    return unsubscribe
  }, [])

  const handleModelSelect = (model: string) => {
    if (model === currentModel) return
    setSelectedModel(model)
    setShowConfirm(true)
  }

  const confirmModelChange = async () => {
    setIsChanging(true)
    setProgress(0)
    setElapsedTime(0)
    setCurrentCount(0)
    setTotalCount(0)
    setCurrentPerson('')
    setRetrainStatus('Switching model and initializing...')

    // Start timer and progress polling
    const startTime = Date.now()
    const timerInterval = setInterval(() => {
      const elapsed = Math.floor((Date.now() - startTime) / 1000)
      setElapsedTime(elapsed)
    }, 500)

    // Poll for progress
    const progressInterval = setInterval(async () => {
      try {
        const progress = await api.getRetrainProgress()
        if (progress.in_progress && progress.total > 0) {
          setCurrentCount(progress.current)
          setTotalCount(progress.total)
          setCurrentPerson(progress.person_name)
          setProgress(Math.round((progress.current / progress.total) * 100))
          setRetrainStatus(`Processing ${progress.person_name} (${progress.current}/${progress.total})`)
        }
      } catch (e) {
        console.error('Failed to fetch progress:', e)
      }
    }, 500)

    try {
      const result = await api.retrainFaceReferences(selectedModel)

      // Calculate final elapsed time
      const finalElapsed = Math.floor((Date.now() - startTime) / 1000)

      clearInterval(timerInterval)
      clearInterval(progressInterval)
      setProgress(100)

      if (result.success) {
        setRetrainStatus(`✓ Successfully re-trained ${result.updated}/${result.total} references in ${finalElapsed}s`)
        onModelChange(selectedModel)
        setShowConfirm(false)
        setTimeout(() => {
          setRetrainStatus('')
          setProgress(0)
          setCurrentCount(0)
          setTotalCount(0)
        }, 5000)
      } else {
        setRetrainStatus(`⚠ Completed with errors: ${result.updated}/${result.total} successful. ${result.errors.join(', ')}`)
      }
    } catch (error: any) {
      clearInterval(timerInterval)
      clearInterval(progressInterval)
      setProgress(0)
      setRetrainStatus(`✗ Failed: ${error.message}`)
    } finally {
      setIsChanging(false)
    }
  }

  return (
    <div>
      <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">InsightFace Model</label>

      <select
        value={currentModel}
        onChange={(e) => handleModelSelect(e.target.value)}
        disabled={isChanging}
        className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
      >
        {models.map(model => (
          <option key={model.value} value={model.value}>
            {model.label} - {model.size}
          </option>
        ))}
      </select>

      <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
        {models.find(m => m.value === currentModel)?.desc}
      </p>

      {showConfirm && (
        <div className="mt-3 p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg">
          <p className="text-sm text-amber-900 dark:text-amber-100 font-medium mb-2">
            ⚠ Switch to {models.find(m => m.value === selectedModel)?.label}?
          </p>
          <p className="text-xs text-amber-700 dark:text-amber-300 mb-3">
            This will automatically re-train all reference faces with the new model. This process may take a few minutes.
          </p>
          <div className="flex gap-2">
            <button
              onClick={confirmModelChange}
              disabled={isChanging}
              className="px-3 py-1.5 text-sm bg-amber-600 hover:bg-amber-700 disabled:bg-slate-400 text-white rounded"
            >
              {isChanging ? 'Re-training...' : 'Confirm & Re-train'}
            </button>
            <button
              onClick={() => {
                setShowConfirm(false)
                setSelectedModel(currentModel)
              }}
              disabled={isChanging}
              className="px-3 py-1.5 text-sm bg-slate-200 hover:bg-slate-300 dark:bg-slate-700 dark:hover:bg-slate-600 text-slate-900 dark:text-slate-100 rounded"
            >
              Cancel
            </button>
          </div>
        </div>
      )}

      {isChanging && (
        <div className="mt-3 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
          <div className="flex items-center justify-between mb-2">
            <span className="text-sm text-blue-900 dark:text-blue-100 font-medium">
              {totalCount > 0 ? `Re-training ${currentCount}/${totalCount}` : 'Initializing...'}
            </span>
            <span className="text-xs text-blue-700 dark:text-blue-300">{elapsedTime}s elapsed</span>
          </div>
          <div className="w-full bg-blue-200 dark:bg-blue-800 rounded-full h-1.5 sm:h-2 overflow-hidden mb-2">
            <div
              className="bg-blue-600 dark:bg-blue-400 h-full transition-all duration-300 ease-out"
              style={{ width: `${progress}%` }}
            />
          </div>
          {currentPerson && (
            <p className="text-xs text-blue-700 dark:text-blue-300 mb-1">
              Processing: <span className="font-medium">{currentPerson}</span>
            </p>
          )}
          <p className="text-xs text-blue-600 dark:text-blue-400">
            {totalCount > 0 ? `${progress}% complete` : 'This may take 1-2 minutes depending on the number of reference faces.'}
          </p>
        </div>
      )}

      {retrainStatus && !isChanging && (
        <div className="mt-2 p-2 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded text-xs text-blue-900 dark:text-blue-100">
          {retrainStatus}
        </div>
      )}
    </div>
  )
}

// CLIP Model Selector (mirrors InsightFaceModelSelector pattern)
function CLIPModelSelector({ currentModel, onModelChange }: { currentModel: string, onModelChange: (model: string) => void }) {
  const queryClient = useQueryClient()
  const [isChanging, setIsChanging] = useState(false)
  const [showConfirm, setShowConfirm] = useState(false)
  const [selectedModel, setSelectedModel] = useState(currentModel)
  const [reindexStatus, setReindexStatus] = useState<string>('')
  const [progress, setProgress] = useState(0)
  const [elapsedTime, setElapsedTime] = useState(0)
  const [currentCount, setCurrentCount] = useState(0)
  const [totalCount, setTotalCount] = useState(0)
  const startTimeRef = useRef<number | null>(null)

  const models = [
    { value: 'clip-ViT-B-32', label: 'CLIP ViT-B/32 (Fastest)', desc: 'Fast, good quality - best for large libraries', dim: '512' },
    { value: 'clip-ViT-B-16', label: 'CLIP ViT-B/16 (Balanced)', desc: 'Better at details, ~1.5x slower', dim: '512' },
    { value: 'clip-ViT-L-14', label: 'CLIP ViT-L/14 (Best Quality)', desc: 'Best accuracy, ~3x slower', dim: '768' },
  ]

  // Detect ongoing indexing on mount and resume progress display
  useEffect(() => {
    let pollInterval: ReturnType<typeof setInterval> | null = null
    let timerInterval: ReturnType<typeof setInterval> | null = null
    let stableCount = 0
    let hasStartedTracking = false

    const checkForOngoingIndexing = async () => {
      try {
        const stats = await api.getSemanticStats()

        // If there are missing embeddings, check if indexing is active
        if (stats.missing_embeddings > 0) {
          // Start polling to detect if count is changing
          let lastCount = stats.total_embeddings

          pollInterval = setInterval(async () => {
            try {
              const newStats = await api.getSemanticStats()

              if (newStats.total_embeddings !== lastCount) {
                // Count is changing - indexing is happening
                if (!hasStartedTracking) {
                  hasStartedTracking = true
                  setIsChanging(true)
                  startTimeRef.current = Date.now()

                  // Start elapsed time counter
                  timerInterval = setInterval(() => {
                    if (startTimeRef.current) {
                      setElapsedTime(Math.floor((Date.now() - startTimeRef.current) / 1000))
                    }
                  }, 500)
                }

                setCurrentCount(newStats.total_embeddings)
                setTotalCount(newStats.total_files)
                setProgress(Math.round((newStats.total_embeddings / newStats.total_files) * 100))
                setReindexStatus(`Re-indexing in progress (${newStats.total_embeddings}/${newStats.total_files})`)
                stableCount = 0
                lastCount = newStats.total_embeddings
              } else if (hasStartedTracking) {
                stableCount++
                if (stableCount >= 5) {
                  // Indexing stopped
                  hasStartedTracking = false
                  setIsChanging(false)
                  startTimeRef.current = null
                  if (timerInterval) clearInterval(timerInterval)
                  if (newStats.missing_embeddings === 0) {
                    setReindexStatus(`✓ Indexing complete (${newStats.total_embeddings} files)`)
                  } else {
                    setReindexStatus('')
                  }
                  setProgress(0)
                  queryClient.invalidateQueries({ queryKey: ['semantic-stats'] })
                }
              }
            } catch (e) {
              console.error('Failed to check indexing status:', e)
            }
          }, 2000)
        }
      } catch (e) {
        console.error('Failed to check initial indexing status:', e)
      }
    }

    checkForOngoingIndexing()

    return () => {
      if (pollInterval) clearInterval(pollInterval)
      if (timerInterval) clearInterval(timerInterval)
    }
  }, []) // eslint-disable-line react-hooks/exhaustive-deps

  const handleModelSelect = (model: string) => {
    if (model === currentModel) return
    setSelectedModel(model)
    setShowConfirm(true)
  }

  const confirmModelChange = async () => {
    setIsChanging(true)
    setProgress(0)
    setElapsedTime(0)
    setCurrentCount(0)
    setTotalCount(0)
    setReindexStatus('Switching model and clearing old embeddings...')

    // Start timer
    const startTime = Date.now()
    const timerInterval = setInterval(() => {
      const elapsed = Math.floor((Date.now() - startTime) / 1000)
      setElapsedTime(elapsed)
    }, 500)

    // Poll for progress
    const progressInterval = setInterval(async () => {
      try {
        const stats = await api.getSemanticStats()
        if (stats.total_files > 0) {
          setCurrentCount(stats.total_embeddings)
          setTotalCount(stats.total_files)
          const pct = Math.round((stats.total_embeddings / stats.total_files) * 100)
          setProgress(pct)
          if (stats.total_embeddings > 0) {
            setReindexStatus(`Re-indexing files with new model (${stats.total_embeddings}/${stats.total_files})`)
          }
        }
      } catch (e) {
        console.error('Failed to fetch progress:', e)
      }
    }, 2000)

    try {
      await api.post('/semantic/settings', { model: selectedModel })

      // Wait for re-indexing to start, then poll until complete
      let lastCount = 0
      let stableCount = 0
      const maxWait = 600 // 10 minutes max

      while (stableCount < 5 && elapsedTime < maxWait) {
        await new Promise(resolve => setTimeout(resolve, 3000))
        const stats = await api.getSemanticStats()
        setCurrentCount(stats.total_embeddings)
        setTotalCount(stats.total_files)
        const pct = Math.round((stats.total_embeddings / stats.total_files) * 100)
        setProgress(pct)

        if (stats.total_embeddings === lastCount && stats.total_embeddings > 0) {
          stableCount++
        } else {
          stableCount = 0
        }
        lastCount = stats.total_embeddings

        if (stats.total_embeddings >= stats.total_files) {
          break
        }
      }

      const finalElapsed = Math.floor((Date.now() - startTime) / 1000)
      clearInterval(timerInterval)
      clearInterval(progressInterval)
      setProgress(100)

      const finalStats = await api.getSemanticStats()
      setReindexStatus(`✓ Successfully re-indexed ${finalStats.total_embeddings}/${finalStats.total_files} files in ${finalElapsed}s`)
      onModelChange(selectedModel)
      setShowConfirm(false)
      queryClient.invalidateQueries({ queryKey: ['semantic-settings'] })
      queryClient.invalidateQueries({ queryKey: ['semantic-stats'] })

      setTimeout(() => {
        setReindexStatus('')
        setProgress(0)
        setCurrentCount(0)
        setTotalCount(0)
      }, 5000)
    } catch (error: any) {
      clearInterval(timerInterval)
      clearInterval(progressInterval)
      setProgress(0)
      setReindexStatus(`✗ Failed: ${error.message}`)
    } finally {
      setIsChanging(false)
    }
  }

  return (
    <div>
      <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">CLIP Model</label>

      <select
        value={currentModel}
        onChange={(e) => handleModelSelect(e.target.value)}
        disabled={isChanging}
        className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
      >
        {models.map(model => (
          <option key={model.value} value={model.value}>
            {model.label} - {model.dim}D
          </option>
        ))}
      </select>

      <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
        {models.find(m => m.value === currentModel)?.desc}
      </p>

      {showConfirm && (
        <div className="mt-3 p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg">
          <p className="text-sm text-amber-900 dark:text-amber-100 font-medium mb-2">
            Switch to {models.find(m => m.value === selectedModel)?.label}?
          </p>
          <p className="text-xs text-amber-700 dark:text-amber-300 mb-3">
            This will clear all embeddings and re-index all files with the new model. This process may take several minutes depending on your library size.
          </p>
          <div className="flex gap-2">
            <button
              onClick={confirmModelChange}
              disabled={isChanging}
              className="px-3 py-1.5 text-sm bg-amber-600 hover:bg-amber-700 disabled:bg-slate-400 text-white rounded"
            >
              {isChanging ? 'Re-indexing...' : 'Confirm & Re-index'}
            </button>
            <button
              onClick={() => {
                setShowConfirm(false)
                setSelectedModel(currentModel)
              }}
              disabled={isChanging}
              className="px-3 py-1.5 text-sm bg-slate-200 hover:bg-slate-300 dark:bg-slate-700 dark:hover:bg-slate-600 text-slate-900 dark:text-slate-100 rounded"
            >
              Cancel
            </button>
          </div>
        </div>
      )}

      {isChanging && (
        <div className="mt-3 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
          <div className="flex items-center justify-between mb-2">
            <span className="text-sm text-blue-900 dark:text-blue-100 font-medium">
              {totalCount > 0 ? `Re-indexing ${currentCount}/${totalCount}` : 'Initializing...'}
            </span>
            <span className="text-xs text-blue-700 dark:text-blue-300">{elapsedTime}s elapsed</span>
          </div>
          <div className="w-full bg-blue-200 dark:bg-blue-800 rounded-full h-1.5 sm:h-2 overflow-hidden mb-2">
            <div
              className="bg-blue-600 dark:bg-blue-400 h-full transition-all duration-300 ease-out"
              style={{ width: `${progress}%` }}
            />
          </div>
          <p className="text-xs text-blue-600 dark:text-blue-400">
            {totalCount > 0 ? `${progress}% complete` : 'This may take several minutes depending on library size.'}
          </p>
        </div>
      )}

      {reindexStatus && !isChanging && (
        <div className="mt-2 p-2 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded text-xs text-blue-900 dark:text-blue-100">
          {reindexStatus}
        </div>
      )}
    </div>
  )
}

// AI Search Tab
function AISearchTab() {
  const queryClient = useQueryClient()
  const [isIndexing, setIsIndexing] = useState(false)
  const [elapsedTime, setElapsedTime] = useState(0)
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null)
  const initialCountRef = useRef<number | null>(null)

  // Get semantic search stats - poll faster while indexing
  const { data: stats, isLoading: statsLoading } = useQuery({
    queryKey: ['semantic-stats'],
    queryFn: () => api.getSemanticStats(),
    refetchInterval: isIndexing ? 2000 : 10000,
  })

  // Check backend status on mount and poll it while indexing
  const { data: indexingStatus } = useQuery({
    queryKey: ['semantic-indexing-status'],
    queryFn: () => api.getSemanticIndexingStatus(),
    refetchInterval: isIndexing ? 3000 : 10000,
  })

  // Sync isIndexing state with backend status
  useEffect(() => {
    if (indexingStatus) {
      if (indexingStatus.indexing_running && !isIndexing) {
        // Backend says indexing is running, sync our state
        setIsIndexing(true)
        setElapsedTime(indexingStatus.elapsed_seconds || 0)
        // Start timer
        if (!timerRef.current) {
          timerRef.current = setInterval(() => {
            setElapsedTime(prev => prev + 1)
          }, 1000)
        }
      } else if (!indexingStatus.indexing_running && isIndexing) {
        // Backend says indexing stopped
        setIsIndexing(false)
        setElapsedTime(0)
        initialCountRef.current = null
        if (timerRef.current) {
          clearInterval(timerRef.current)
          timerRef.current = null
        }
      }
    }
  }, [indexingStatus, isIndexing])

  // Cleanup timer on unmount
  useEffect(() => {
    return () => {
      if (timerRef.current) clearInterval(timerRef.current)
    }
  }, [])

  // Get current model setting
  const { data: settings } = useQuery({
    queryKey: ['semantic-settings'],
    queryFn: async () => {
      try {
        const response = await api.get<{ model: string; threshold: number }>('/semantic/settings')
        return response
      } catch {
        return { model: 'clip-ViT-B-32', threshold: 0.2 }
      }
    },
  })

  // Start indexing tracking
  const startIndexingTracking = () => {
    setIsIndexing(true)
    setElapsedTime(0)
    initialCountRef.current = stats?.total_embeddings || null
    if (timerRef.current) clearInterval(timerRef.current)
    timerRef.current = setInterval(() => {
      setElapsedTime(prev => prev + 1)
    }, 1000)
    // Invalidate status query to refresh
    queryClient.invalidateQueries({ queryKey: ['semantic-indexing-status'] })
  }

  // Re-index mutation
  const reindexMutation = useMutation({
    mutationFn: async () => {
      return api.post('/semantic/reindex', {})
    },
    onSuccess: () => {
      startIndexingTracking()
      queryClient.invalidateQueries({ queryKey: ['semantic-stats'] })
    },
    onError: (err: unknown) => {
      notificationManager.apiError('Error', err, 'Failed to start re-indexing')
    }
  })

  // Clear embeddings mutation
  const clearMutation = useMutation({
    mutationFn: async () => {
      return api.post('/semantic/clear', {})
    },
    onSuccess: () => {
      notificationManager.success('Embeddings Cleared', 'All embeddings have been removed')
      queryClient.invalidateQueries({ queryKey: ['semantic-stats'] })
    },
    onError: (err: unknown) => {
      notificationManager.apiError('Error', err, 'Failed to clear embeddings')
    }
  })

  const progress = stats ? Math.round((stats.total_embeddings / stats.total_files) * 100) : 0

  return (
    <div className="space-y-6">
      <div>
        <h2 className="text-xl font-semibold text-slate-900 dark:text-slate-100 mb-2">AI Search Settings</h2>
        <p className="text-slate-600 dark:text-slate-400">
          Configure the CLIP model used for semantic image search
        </p>
      </div>

      {/* Current Status */}
      <div className="bg-slate-50 dark:bg-slate-900/50 rounded-lg p-4">
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-sm font-medium text-slate-700 dark:text-slate-300">Index Status</h3>
          {isIndexing && (
            <div className="flex items-center gap-2 px-2 py-1 bg-blue-100 dark:bg-blue-900/30 rounded">
              <Loader2 className="w-3 h-3 animate-spin text-blue-600 dark:text-blue-400" />
              <span className="text-xs text-blue-700 dark:text-blue-300">Indexing...</span>
            </div>
          )}
        </div>
        {statsLoading ? (
          <div className="flex items-center gap-2 text-slate-500">
            <Loader2 className="w-4 h-4 animate-spin" />
            Loading...
          </div>
        ) : stats ? (
          <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
            <div>
              <p className="text-2xl font-bold text-slate-900 dark:text-slate-100">{stats.total_embeddings.toLocaleString()}</p>
              <p className="text-sm text-slate-500">Indexed Files</p>
            </div>
            <div>
              <p className="text-2xl font-bold text-slate-900 dark:text-slate-100">{stats.total_files.toLocaleString()}</p>
              <p className="text-sm text-slate-500">Total Files</p>
            </div>
            <div>
              <p className="text-2xl font-bold text-blue-600">{stats.coverage_percent}%</p>
              <p className="text-sm text-slate-500">Coverage</p>
            </div>
            <div>
              <p className="text-2xl font-bold text-slate-900 dark:text-slate-100">{stats.missing_embeddings.toLocaleString()}</p>
              <p className="text-sm text-slate-500">Not Indexed</p>
            </div>
          </div>
        ) : null}

        {/* Progress bar when indexing */}
        {isIndexing && stats && (
          <div className="mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
            <div className="flex items-center justify-between mb-2">
              <span className="text-sm text-blue-900 dark:text-blue-100 font-medium">
                Re-indexing {stats.total_embeddings.toLocaleString()}/{stats.total_files.toLocaleString()}
              </span>
              <span className="text-xs text-blue-700 dark:text-blue-300">{elapsedTime}s elapsed</span>
            </div>
            <div className="w-full bg-blue-200 dark:bg-blue-800 rounded-full h-1.5 sm:h-2 overflow-hidden mb-2">
              <div
                className="bg-blue-600 dark:bg-blue-400 h-full transition-all duration-300 ease-out"
                style={{ width: `${progress}%` }}
              />
            </div>
            <p className="text-xs text-blue-600 dark:text-blue-400">{progress}% complete</p>
          </div>
        )}
      </div>

      {/* Model Selection */}
      <div className="space-y-4">
        <CLIPModelSelector
          currentModel={settings?.model || 'clip-ViT-B-32'}
          onModelChange={() => {
            startIndexingTracking()
            queryClient.invalidateQueries({ queryKey: ['semantic-settings'] })
          }}
        />
      </div>

      {/* Actions */}
      <div className="space-y-4 pt-4 border-t border-slate-200 dark:border-slate-700">
        <h3 className="text-sm font-medium text-slate-700 dark:text-slate-300">Index Actions</h3>
        <div className="flex flex-wrap gap-3">
          <button
            onClick={() => reindexMutation.mutate()}
            disabled={reindexMutation.isPending || isIndexing}
            className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 disabled:opacity-50 flex items-center gap-2"
          >
            {reindexMutation.isPending ? (
              <Loader2 className="w-4 h-4 animate-spin" />
            ) : (
              <RefreshCw className="w-4 h-4" />
            )}
            Re-index All Files
          </button>
          <button
            onClick={() => {
              if (confirm('Are you sure you want to clear all embeddings? This cannot be undone.')) {
                clearMutation.mutate()
              }
            }}
            disabled={clearMutation.isPending}
            className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50 flex items-center gap-2"
          >
            {clearMutation.isPending ? (
              <Loader2 className="w-4 h-4 animate-spin" />
            ) : (
              <Trash2 className="w-4 h-4" />
            )}
            Clear All Embeddings
          </button>
        </div>
        <p className="text-sm text-slate-500 dark:text-slate-400">
          Re-indexing will regenerate embeddings for all files using the current model. This runs in the background.
        </p>
      </div>

      {/* Info */}
      <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
        <h4 className="font-medium text-blue-900 dark:text-blue-100 mb-2">About CLIP Models</h4>
        <ul className="text-sm text-blue-700 dark:text-blue-300 space-y-1">
          <li>• <strong>ViT-B/32</strong>: Fastest, good for large libraries. Best balance of speed and quality.</li>
          <li>• <strong>ViT-B/16</strong>: Better at details, slightly slower. Good middle ground.</li>
          <li>• <strong>ViT-L/14</strong>: Best accuracy, significantly slower. Recommended for smaller libraries or when quality is critical.</li>
        </ul>
      </div>

    </div>
  )
}

function FaceRecognitionTab() {
  const [editedConfig, setEditedConfig] = useState<any>(null)
  const queryClient = useQueryClient()

  const { data: config, isLoading } = useQuery({
    queryKey: ['config'],
    queryFn: () => api.getConfig(),
  })

  // Sync editedConfig with query data (initial load and after save/refetch)
  useEffect(() => {
    if (config) {
      setEditedConfig(config)
    }
  }, [config])

  const updateMutation = useMutation({
    mutationFn: (newConfig: any) => api.updateConfig(newConfig),
    onSuccess: () => {
      notificationManager.settingsSaved('Face recognition')
      queryClient.invalidateQueries({ queryKey: ['config'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Face recognition')
    },
  })

  if (isLoading || !editedConfig) {
    return <div className="text-center py-8 text-slate-600 dark:text-slate-400">Loading configuration...</div>
  }

  const faceRecognitionSettings = editedConfig.face_recognition || {}

  const updateFaceRecognitionSettings = (updates: any) => {
    const updatedConfig = {
      ...editedConfig,
      face_recognition: {
        ...editedConfig.face_recognition,
        ...updates
      }
    }
    setEditedConfig(updatedConfig)
    updateMutation.mutate(updatedConfig)
  }

  return (
    <div className="space-y-6">
      {/* Face Recognition */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Face Recognition</h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={faceRecognitionSettings.enabled || false}
              onChange={(e) => updateFaceRecognitionSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
          Automatically detect faces in downloaded media and route to review queue if no match found.
        </p>
        <div className="p-3 bg-slate-50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg mb-4">
          <p className="text-xs text-slate-600 dark:text-slate-400">
            <strong>Technology:</strong> InsightFace (ArcFace + RetinaFace) - State-of-the-art face recognition with 99.8% accuracy, 6x faster than previous DeepFace implementation
          </p>
        </div>
        {faceRecognitionSettings.enabled && (
          <div className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Person Name
              </label>
              <input
                type="text"
                value={faceRecognitionSettings.person_name || ''}
                onChange={(e) => updateFaceRecognitionSettings({ person_name: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                placeholder="Eva Longoria"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Name used for matching reference faces
              </p>
            </div>
            <div>
              <InsightFaceModelSelector
                currentModel={faceRecognitionSettings.insightface_model || 'buffalo_l'}
                onModelChange={(newModel) => updateFaceRecognitionSettings({ insightface_model: newModel })}
              />
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Tolerance (0.0 - 1.0)
              </label>
              <input
                type="number"
                step="0.05"
                min="0"
                max="1"
                value={faceRecognitionSettings.tolerance || 0.20}
                onChange={(e) => updateFaceRecognitionSettings({ tolerance: parseFloat(e.target.value) })}
                className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Lower = stricter matching. Recommended: 0.15-0.20 for images. Range: 0.0-1.0
              </p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Review Queue Path
              </label>
              <input
                type="text"
                value={faceRecognitionSettings.review_path || ''}
                onChange={(e) => updateFaceRecognitionSettings({ review_path: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                placeholder="/opt/immich/review"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Directory for media that don't match reference faces
              </p>
            </div>

            {/* Video Face Recognition Settings */}
            <div className="border-t border-slate-200 dark:border-slate-700 pt-4 mt-4">
              <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Video Recognition Settings</h4>
              <div className="space-y-4">
                <label className="flex items-center space-x-2 cursor-pointer">
                  <input
                    type="checkbox"
                    checked={faceRecognitionSettings.enable_video_recognition || false}
                    onChange={(e) => updateFaceRecognitionSettings({ enable_video_recognition: e.target.checked })}
                    className="w-4 h-4 rounded"
                  />
                  <span className="text-sm text-slate-600 dark:text-slate-400">Enable video face recognition</span>
                </label>
                <p className="text-xs text-slate-500 dark:text-slate-400 ml-6">
                  Extract frames from videos and check for faces. May be resource-intensive for large videos.
                </p>

                {faceRecognitionSettings.enable_video_recognition && (
                  <>
                    <div>
                      <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                        Video Tolerance (0.0 - 1.0)
                      </label>
                      <input
                        type="number"
                        step="0.05"
                        min="0"
                        max="1"
                        value={faceRecognitionSettings.video_tolerance || 0.30}
                        onChange={(e) => updateFaceRecognitionSettings({ video_tolerance: parseFloat(e.target.value) })}
                        className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                      />
                      <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                        Video frames are harder to match. Recommended: 0.25-0.35
                      </p>
                    </div>
                    <div>
                      <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                        Video Frame Count
                      </label>
                      <input
                        type="number"
                        min="1"
                        max="10"
                        value={faceRecognitionSettings.video_face_frames || 3}
                        onChange={(e) => updateFaceRecognitionSettings({ video_face_frames: parseInt(e.target.value) })}
                        className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                      />
                      <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                        Number of frames to extract and check per video (default: 3). Higher = more accurate but slower.
                      </p>
                    </div>
                  </>
                )}
              </div>
            </div>

            {/* Source-Based Tolerance */}
            <div className="border-t border-slate-200 dark:border-slate-700 pt-4 mt-4">
              <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Source-Based Tolerance</h4>
              <p className="text-xs text-slate-500 dark:text-slate-400 mb-3">
                Set different matching thresholds for trusted sources. Useful for accepting group photos or unusual angles from her own account while maintaining strict matching for third-party content.
              </p>
              <SourceToleranceManager
                sourceTolerances={faceRecognitionSettings.source_tolerances || {}}
                onUpdate={(newTolerances) => updateFaceRecognitionSettings({ source_tolerances: newTolerances })}
              />
            </div>

            {/* False Positive Prevention Info */}
            <div className="p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg mt-4">
              <h5 className="text-sm font-medium text-blue-900 dark:text-blue-100 mb-1">Automatic False Positive Prevention</h5>
              <ul className="text-xs text-blue-700 dark:text-blue-300 space-y-1">
                <li>• Filters faces smaller than 80×80 pixels (text, logos, distant faces)</li>
                <li>• Rejects unusual aspect ratios to prevent text pattern matches</li>
                <li>• Requires 95%+ confidence in crowd scenes (3+ faces per frame) when using strict tolerance (≤0.20)</li>
                <li>• Crowd detection skipped for source-based relaxed tolerances (&gt;0.20)</li>
              </ul>
            </div>

            {/* Reference Face Statistics */}
            <ReferenceStatsSection />

            {/* Reference Faces Management */}
            <div className="border-t border-slate-200 dark:border-slate-700 pt-4 mt-4">
              <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Manage Reference Faces</h4>
              <ReferenceManagementSection personName={faceRecognitionSettings.person_name || 'Eva Longoria'} />
            </div>
          </div>
        )}
      </div>

      {/* Immich Integration */}
      <ImmichIntegrationSection />
    </div>
  )
}

// Immich Face Integration Section
function ImmichIntegrationSection() {
  const [immichStatus, setImmichStatus] = useState<any>(null)
  const [immichStats, setImmichStats] = useState<any>(null)
  const [loading, setLoading] = useState(true)
  const [testLoading, setTestLoading] = useState(false)
  const [enabled, setEnabled] = useState(false)
  const [toggling, setToggling] = useState(false)

  const fetchImmichStatus = async () => {
    try {
      setTestLoading(true)
      const data = await api.getFaceImmichStatus()
      setImmichStatus(data)
      setEnabled(data.enabled ?? false)

      // If connected, fetch statistics
      if (data.connected) {
        const statsData = await api.getFaceImmichStatistics()
        setImmichStats(statsData)
      }
    } catch (error) {
      console.error('Failed to fetch Immich status:', error)
      setImmichStatus({ enabled: false, connected: false, message: 'Failed to connect' })
    } finally {
      setLoading(false)
      setTestLoading(false)
    }
  }

  const toggleEnabled = async () => {
    try {
      setToggling(true)
      const newValue = !enabled
      await api.updateFaceImmichSettings({ enabled: newValue })
      setEnabled(newValue)
      // Refresh status after toggling
      fetchImmichStatus()
    } catch (error) {
      console.error('Failed to toggle Immich integration:', error)
    } finally {
      setToggling(false)
    }
  }

  useEffect(() => {
    fetchImmichStatus()
  }, [])

  return (
    <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
      <div className="flex items-center justify-between mb-4">
        <div className="flex items-center gap-3">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Immich Integration</h3>
          {enabled && immichStatus?.connected && (
            <span className="px-2 py-0.5 text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300 rounded-full">
              Connected
            </span>
          )}
          {/* Enable/Disable Toggle */}
          <button
            onClick={toggleEnabled}
            disabled={toggling || loading}
            className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-slate-900 ${
              enabled
                ? 'bg-blue-600'
                : 'bg-slate-300 dark:bg-slate-600'
            } ${toggling ? 'opacity-50' : ''}`}
          >
            <span
              className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                enabled ? 'translate-x-6' : 'translate-x-1'
              }`}
            />
          </button>
          <span className="text-sm text-slate-600 dark:text-slate-400">
            {enabled ? 'Enabled' : 'Disabled'}
          </span>
        </div>
        <button
          onClick={fetchImmichStatus}
          disabled={testLoading || !enabled}
          className="text-sm px-3 py-1.5 bg-slate-100 hover:bg-slate-200 dark:bg-slate-700 dark:hover:bg-slate-600 text-slate-700 dark:text-slate-300 rounded-lg transition-colors disabled:opacity-50"
        >
          {testLoading ? 'Testing...' : 'Test Connection'}
        </button>
      </div>

      <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
        Use Immich's face database to identify people in new downloads. Faces are detected locally with InsightFace and matched against Immich's named faces using embedding comparison.
      </p>

      {loading ? (
        <div className="text-center py-4 text-slate-500">Loading Immich status...</div>
      ) : !enabled ? (
        <div className="p-3 bg-slate-50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg text-center">
          <p className="text-sm text-slate-500 dark:text-slate-400">
            Enable the toggle above to use Immich's face database for identifying people in downloads.
          </p>
        </div>
      ) : (
        <div className="space-y-4">
          {/* Connection Status */}
          <div className={`p-3 rounded-lg ${
            immichStatus?.connected
              ? 'bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800'
              : 'bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800'
          }`}>
            <div className="flex items-center gap-2">
              <span className={`w-2 h-2 rounded-full ${immichStatus?.connected ? 'bg-green-500' : 'bg-amber-500'}`} />
              <span className={`text-sm font-medium ${
                immichStatus?.connected
                  ? 'text-green-800 dark:text-green-200'
                  : 'text-amber-800 dark:text-amber-200'
              }`}>
                {immichStatus?.message || 'Unknown status'}
              </span>
            </div>
            {immichStatus?.server_info && (
              <p className="text-xs text-green-700 dark:text-green-300 mt-1 ml-4">
                Immich v{immichStatus.server_info.major}.{immichStatus.server_info.minor}.{immichStatus.server_info.patch}
              </p>
            )}
            {immichStatus?.api_url && (
              <p className="text-xs text-slate-600 dark:text-slate-400 mt-1 ml-4">
                API: {immichStatus.api_url}
              </p>
            )}
          </div>

          {/* Statistics (if connected) */}
          {immichStatus?.connected && immichStats && (
            <div className="grid grid-cols-3 gap-3">
              <div className="p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg text-center">
                <div className="text-2xl font-bold text-slate-900 dark:text-slate-100">
                  {immichStats.total_people?.toLocaleString()}
                </div>
                <div className="text-xs text-slate-600 dark:text-slate-400">Total Faces</div>
              </div>
              <div className="p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg text-center">
                <div className="text-2xl font-bold text-blue-600 dark:text-blue-400">
                  {immichStats.named_people?.toLocaleString()}
                </div>
                <div className="text-xs text-slate-600 dark:text-slate-400">Named People</div>
              </div>
              <div className="p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg text-center">
                <div className="text-2xl font-bold text-slate-500 dark:text-slate-400">
                  {immichStats.unnamed_people?.toLocaleString()}
                </div>
                <div className="text-xs text-slate-600 dark:text-slate-400">Unnamed</div>
              </div>
            </div>
          )}

          {/* Top Named People */}
          {immichStatus?.connected && immichStats?.people_by_face_count?.length > 0 && (
            <div>
              <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Named People in Immich</h4>
              <div className="flex flex-wrap gap-2">
                {immichStats.people_by_face_count.slice(0, 10).map((person: any, idx: number) => (
                  <span
                    key={idx}
                    className="px-2 py-1 text-xs bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-full"
                  >
                    {person.name}
                  </span>
                ))}
                {immichStats.people_by_face_count.length > 10 && (
                  <span className="px-2 py-1 text-xs text-slate-500">
                    +{immichStats.people_by_face_count.length - 10} more
                  </span>
                )}
              </div>
            </div>
          )}

          {/* Configuration Info */}
          <div className="p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
            <h5 className="text-sm font-medium text-blue-900 dark:text-blue-100 mb-1">How It Works</h5>
            <ul className="text-xs text-blue-700 dark:text-blue-300 space-y-1">
              <li>• Detects faces locally using InsightFace with the <code className="bg-blue-100 dark:bg-blue-800 px-1 rounded">buffalo_l</code> model</li>
              <li>• Compares face embeddings against Immich's PostgreSQL database of named faces</li>
              <li>• Uses cosine similarity to find closest match (threshold: 80% confidence)</li>
              <li>• Works on new downloads before they're imported into Immich</li>
              <li>• Both systems use compatible 512-dimensional embeddings</li>
            </ul>
          </div>
        </div>
      )}
    </div>
  )
}

// Easynews Configuration Section Component
function EasynewsConfigSection() {
  const queryClient = useQueryClient()
  const [localConfig, setLocalConfig] = useState<any>(null)

  const { data: configData, isLoading } = useQuery({
    queryKey: ['easynews-config'],
    queryFn: () => api.getEasynewsConfig(),
  })

  useEffect(() => {
    if (configData?.config && !localConfig) {
      setLocalConfig(configData.config)
    }
  }, [configData, localConfig])

  const updateMutation = useMutation({
    mutationFn: (config: any) => api.updateEasynewsConfig(config),
    onSuccess: () => {
      notificationManager.settingsSaved('Easynews')
      queryClient.invalidateQueries({ queryKey: ['easynews-config'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Easynews')
    },
  })

  const testMutation = useMutation({
    mutationFn: () => api.testEasynewsConnection(),
    onSuccess: (data) => {
      if (data.success) {
        notificationManager.connectionSuccess('Easynews', data.message)
      } else {
        notificationManager.connectionFailed('Easynews', data.message)
      }
    },
    onError: (err: unknown) => {
      notificationManager.connectionFailed('Easynews', err)
    },
  })

  const handleSave = () => {
    if (localConfig) {
      updateMutation.mutate(localConfig)
    }
  }

  const updateConfig = (updates: any) => {
    setLocalConfig((prev: any) => ({ ...prev, ...updates }))
  }

  if (isLoading || !localConfig) {
    return (
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="animate-pulse">
          <div className="h-6 bg-slate-200 dark:bg-slate-700 rounded w-32 mb-4"></div>
          <div className="space-y-3">
            <div className="h-10 bg-slate-200 dark:bg-slate-700 rounded"></div>
            <div className="h-10 bg-slate-200 dark:bg-slate-700 rounded"></div>
          </div>
        </div>
      </div>
    )
  }

  return (
    <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
      <div className="flex items-center justify-between mb-4">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 flex items-center space-x-2">
          <Download className="w-5 h-5" />
          <span>Easynews</span>
        </h3>
        <label className="flex items-center space-x-2 cursor-pointer">
          <input
            type="checkbox"
            checked={localConfig.enabled || false}
            onChange={(e) => updateConfig({ enabled: e.target.checked })}
            className="w-4 h-4 rounded"
          />
          <span className="text-sm text-slate-600 dark:text-slate-400">Enable Scheduled Checks</span>
        </label>
      </div>

      <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
        Configure Easynews credentials for searching and downloading media files. Supports automatic checks on a schedule.
      </p>

      <div className="space-y-4">
        {/* Credentials */}
        <div className="grid grid-cols-2 gap-4">
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Username
            </label>
            <input
              type="text"
              value={localConfig.username || ''}
              onChange={(e) => updateConfig({ username: e.target.value })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              placeholder="Easynews username"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Password
            </label>
            <input
              type="password"
              value={localConfig.password || ''}
              onChange={(e) => updateConfig({ password: e.target.value })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              placeholder="Easynews password"
            />
          </div>
        </div>

        {/* Check Settings */}
        <div className="grid grid-cols-2 gap-4">
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Check Interval
            </label>
            <select
              value={localConfig.check_interval_hours || 12}
              onChange={(e) => updateConfig({ check_interval_hours: parseInt(e.target.value) })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
            >
              <option value={6}>Every 6 hours</option>
              <option value={12}>Every 12 hours (2x daily)</option>
              <option value={24}>Every 24 hours (daily)</option>
            </select>
          </div>
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Minimum Quality
            </label>
            <select
              value={localConfig.min_quality || '720p'}
              onChange={(e) => updateConfig({ min_quality: e.target.value })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
            >
              <option value="360p">360p+</option>
              <option value="480p">480p+</option>
              <option value="720p">720p+</option>
              <option value="1080p">1080p+</option>
              <option value="2160p">4K only</option>
            </select>
          </div>
        </div>

        {/* Auto Download */}
        <label className="flex items-center space-x-2 cursor-pointer">
          <input
            type="checkbox"
            checked={localConfig.auto_download || false}
            onChange={(e) => updateConfig({ auto_download: e.target.checked })}
            className="w-4 h-4 rounded"
          />
          <span className="text-sm text-slate-600 dark:text-slate-400">Auto-download new matches</span>
        </label>

        {/* Push Notifications */}
        <label className="flex items-center space-x-2 cursor-pointer">
          <input
            type="checkbox"
            checked={localConfig.notifications_enabled ?? true}
            onChange={(e) => updateConfig({ notifications_enabled: e.target.checked })}
            className="w-4 h-4 rounded"
          />
          <span className="text-sm text-slate-600 dark:text-slate-400">Send push notifications for scheduled scans</span>
        </label>

        {/* Proxy Settings */}
        <div className="border-t border-slate-200 dark:border-slate-700 pt-4 mt-4">
          <label className="flex items-center space-x-2 cursor-pointer mb-4">
            <input
              type="checkbox"
              checked={localConfig.proxy_enabled || false}
              onChange={(e) => updateConfig({ proxy_enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Use Proxy</span>
          </label>

          {localConfig.proxy_enabled && (
            <div className="space-y-3">
              <div className="grid grid-cols-4 gap-4">
                <div>
                  <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                    Type
                  </label>
                  <select
                    value={localConfig.proxy_type || 'http'}
                    onChange={(e) => updateConfig({ proxy_type: e.target.value })}
                    className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  >
                    <option value="http">HTTP</option>
                    <option value="https">HTTPS</option>
                    <option value="socks4">SOCKS4</option>
                    <option value="socks5">SOCKS5</option>
                  </select>
                </div>
                <div className="col-span-2">
                  <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                    Host
                  </label>
                  <input
                    type="text"
                    value={localConfig.proxy_host || ''}
                    onChange={(e) => updateConfig({ proxy_host: e.target.value })}
                    className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                    placeholder="proxy.example.com"
                  />
                </div>
                <div>
                  <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                    Port
                  </label>
                  <input
                    type="number"
                    value={localConfig.proxy_port || ''}
                    onChange={(e) => updateConfig({ proxy_port: parseInt(e.target.value) || null })}
                    className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                    placeholder="8080"
                  />
                </div>
              </div>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                    Proxy Username (optional)
                  </label>
                  <input
                    type="text"
                    value={localConfig.proxy_username || ''}
                    onChange={(e) => updateConfig({ proxy_username: e.target.value })}
                    className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                    placeholder="Proxy username"
                  />
                </div>
                <div>
                  <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                    Proxy Password (optional)
                  </label>
                  <input
                    type="password"
                    value={localConfig.proxy_password || ''}
                    onChange={(e) => updateConfig({ proxy_password: e.target.value })}
                    className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                    placeholder="Proxy password"
                  />
                </div>
              </div>
            </div>
          )}
        </div>

        {/* Actions */}
        <div className="flex justify-between items-center pt-4">
          <button
            onClick={() => testMutation.mutate()}
            disabled={testMutation.isPending || !localConfig.username || !localConfig.password}
            className="flex items-center space-x-2 px-4 py-2 bg-slate-600 hover:bg-slate-700 disabled:bg-slate-400 text-white rounded-lg transition-colors"
          >
            {testMutation.isPending ? (
              <Loader2 className="w-4 h-4 animate-spin" />
            ) : (
              <RefreshCw className="w-4 h-4" />
            )}
            <span>Test Connection</span>
          </button>
          <button
            onClick={handleSave}
            disabled={updateMutation.isPending}
            className="flex items-center space-x-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white rounded-lg transition-colors"
          >
            {updateMutation.isPending ? (
              <Loader2 className="w-4 h-4 animate-spin" />
            ) : (
              <Save className="w-4 h-4" />
            )}
            <span>Save Easynews Settings</span>
          </button>
        </div>
      </div>
    </div>
  )
}

function DownloadsTab() {
  const [editedConfig, setEditedConfig] = useState<any>(null)
  const [queueSettings, setQueueSettings] = useState<any>({
    download_delay_seconds: 15,
    base_directory: '/opt/immich/md',
    stop_on_cookie_error: true,
    send_cookie_notification: true
  })
  const [antibotSettings, setAntibotSettings] = useState<any>({
    browser: 'edge',
    custom_user_agent: '',
    limit_rate: '2M',
    throttled_rate: '100K',
    sleep_requests_min: 1,
    sleep_requests_max: 3,
    retries: 10,
    fragment_retries: 10,
    concurrent_fragments: 1,
    socket_timeout: 30,
    enabled: true
  })
  const queryClient = useQueryClient()

  const { data: config, isLoading } = useQuery({
    queryKey: ['config'],
    queryFn: () => api.getConfig(),
  })

  // Fetch video queue settings
  const { data: queueData } = useQuery({
    queryKey: ['video-queue-settings'],
    queryFn: () => api.getVideoQueueSettings(),
  })

  // Fetch anti-bot settings
  const { data: antibotData } = useQuery({
    queryKey: ['antibot-settings'],
    queryFn: () => api.getAntibotSettings(),
  })

  // Sync states with query data (handles cached data case)
  useEffect(() => {
    if (config && !editedConfig) {
      setEditedConfig(config)
    }
  }, [config, editedConfig])

  useEffect(() => {
    if (queueData?.settings) {
      setQueueSettings(queueData.settings)
    }
  }, [queueData])

  useEffect(() => {
    if (antibotData?.settings) {
      setAntibotSettings(antibotData.settings)
    }
  }, [antibotData])

  const updateMutation = useMutation({
    mutationFn: (newConfig: any) => api.updateConfig(newConfig),
    onSuccess: () => {
      notificationManager.settingsSaved('Download')
      queryClient.invalidateQueries({ queryKey: ['config'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Download')
    },
  })

  // Mutation for video queue settings
  const updateQueueMutation = useMutation({
    mutationFn: (settings: any) => api.updateVideoQueueSettings(settings),
    onSuccess: () => {
      notificationManager.settingsSaved('Download queue')
      queryClient.invalidateQueries({ queryKey: ['video-queue-settings'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Queue')
    },
  })

  // Mutation for anti-bot settings
  const updateAntibotMutation = useMutation({
    mutationFn: (settings: any) => api.updateAntibotSettings(settings),
    onSuccess: () => {
      notificationManager.settingsSaved('Anti-bot')
      queryClient.invalidateQueries({ queryKey: ['antibot-settings'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Anti-bot')
    },
  })

  const handleSave = () => {
    if (editedConfig) {
      updateMutation.mutate(editedConfig)
    }
  }

  const handleSaveQueueSettings = () => {
    updateQueueMutation.mutate(queueSettings)
  }

  const handleSaveAntibotSettings = () => {
    updateAntibotMutation.mutate(antibotSettings)
  }

  const updateQueueSettings = (updates: any) => {
    setQueueSettings((prev: any) => ({ ...prev, ...updates }))
  }

  const updateAntibotSettingsState = (updates: any) => {
    setAntibotSettings((prev: any) => ({ ...prev, ...updates }))
  }

  const updateImmichSettings = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      immich: {
        ...prev.immich,
        ...updates
      }
    }))
  }

  const updatePushoverSettings = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      pushover: {
        ...prev.pushover,
        ...updates
      }
    }))
  }

  const updateRepostDetectionSettings = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      repost_detection: {
        ...prev.repost_detection,
        ...updates
      }
    }))
  }

  const updateInstagramPerceptualDuplicatesSettings = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      instagram_perceptual_duplicates: {
        ...prev.instagram_perceptual_duplicates,
        ...updates
      }
    }))
  }

  const updateRecycleBinSettings = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      recycle_bin: {
        ...prev.recycle_bin,
        ...updates
      }
    }))
  }

  const updateFileOwnershipSettings = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      file_ownership: {
        ...prev.file_ownership,
        ...updates
      }
    }))
  }

  const updateVideoDownloaderSettings = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      video_downloader: {
        ...prev.video_downloader,
        ...updates
      }
    }))
  }

  if (isLoading || !editedConfig) return <div>Loading...</div>

  const immichSettings = editedConfig.immich || {}
  const repostDetectionSettings = editedConfig.repost_detection || {}
  const instagramPerceptualDuplicatesSettings = editedConfig.instagram_perceptual_duplicates || {}
  const pushoverSettings = editedConfig.pushover || {}
  const recycleBinSettings = editedConfig.recycle_bin || {}
  const fileOwnershipSettings = editedConfig.file_ownership || {}
  const videoDownloaderSettings = editedConfig.video_downloader || {}

  return (
    <div className="space-y-6">
      {/* Video Downloader Settings */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4 flex items-center space-x-2">
          <Video className="w-5 h-5" />
          <span>Video Downloader</span>
        </h3>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          Configure the universal video downloader that supports YouTube, Vimeo, Dailymotion, Bilibili, and 20+ gallery/image sites via gallery-dl.
        </p>
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Default Download Path
            </label>
            <input
              type="text"
              value={videoDownloaderSettings.base_path || '/opt/immich/md'}
              onChange={(e) => updateVideoDownloaderSettings({ base_path: e.target.value })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              placeholder="/opt/immich/md"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
              Base directory for video downloads. Platform-specific folders will be created automatically.
            </p>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Max Concurrent Downloads
              </label>
              <input
                type="number"
                min="1"
                max="10"
                value={videoDownloaderSettings.max_concurrent || 3}
                onChange={(e) => updateVideoDownloaderSettings({ max_concurrent: parseInt(e.target.value) })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Maximum simultaneous downloads (1-10)
              </p>
            </div>
          </div>

          <div className="flex flex-col space-y-2">
            <label className="flex items-center space-x-2 cursor-pointer">
              <input
                type="checkbox"
                checked={videoDownloaderSettings.cache_thumbnails !== false}
                onChange={(e) => updateVideoDownloaderSettings({ cache_thumbnails: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <span className="text-sm text-slate-600 dark:text-slate-400">Cache video thumbnails from platforms</span>
            </label>
            <label className="flex items-center space-x-2 cursor-pointer">
              <input
                type="checkbox"
                checked={videoDownloaderSettings.auto_generate_thumbnails !== false}
                onChange={(e) => updateVideoDownloaderSettings({ auto_generate_thumbnails: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <span className="text-sm text-slate-600 dark:text-slate-400">Auto-generate thumbnails for downloaded files</span>
            </label>
            <label className="flex items-center space-x-2 cursor-pointer">
              <input
                type="checkbox"
                checked={videoDownloaderSettings.embed_metadata !== false}
                onChange={(e) => updateVideoDownloaderSettings({ embed_metadata: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <span className="text-sm text-slate-600 dark:text-slate-400">Embed metadata in downloaded files</span>
            </label>
          </div>

          <div className="p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
            <p className="text-xs text-blue-700 dark:text-blue-300">
              <strong>Supported platforms:</strong> YouTube, Vimeo, Dailymotion, Bilibili (via yt-dlp), plus Erome, Bunkr, Cyberdrop, Kemono, Coomer, Pixeldrain, GoFile, ImgBox, ImageBam, Fapello, ImageFap, and more (via gallery-dl).
            </p>
          </div>
        </div>
      </div>

      {/* Download Queue Settings */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4 flex items-center space-x-2">
          <Download className="w-5 h-5" />
          <span>Download Queue</span>
        </h3>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          Configure settings for the video download queue processor. These settings help avoid rate limiting when downloading large batches of videos.
        </p>
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Download Base Directory
            </label>
            <input
              type="text"
              value={queueSettings.base_directory || '/opt/immich/md'}
              onChange={(e) => updateQueueSettings({ base_directory: e.target.value })}
              className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              placeholder="/opt/immich/md"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
              Base directory for all downloads. Platform subdirectories (youtube, erome, etc.) will be created automatically.
            </p>
          </div>

          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Delay Between Downloads (seconds)
            </label>
            <input
              type="number"
              min="0"
              max="120"
              value={queueSettings.download_delay_seconds || 15}
              onChange={(e) => updateQueueSettings({ download_delay_seconds: parseInt(e.target.value) || 0 })}
              className="w-24 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
              Wait time between each video download (0-120 seconds). Higher values reduce rate limiting risk.
            </p>
          </div>

          <div className="p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg">
            <p className="text-xs text-amber-700 dark:text-amber-300">
              <strong>Rate limiting:</strong> YouTube and other platforms may throttle or block downloads if too many requests are made too quickly. A delay of 10-30 seconds between downloads is recommended for large queues. You can also add cookies in the Scrapers page for better rate limits.
            </p>
          </div>

          {/* Cookie Expiration Handling */}
          <div className="border-t border-slate-200 dark:border-slate-700 pt-4 mt-4">
            <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Cookie Expiration Handling</h4>

            <div className="space-y-3">
              <label className="flex items-center space-x-3 cursor-pointer">
                <input
                  type="checkbox"
                  checked={queueSettings.stop_on_cookie_error !== false}
                  onChange={(e) => updateQueueSettings({ stop_on_cookie_error: e.target.checked })}
                  className="w-4 h-4 rounded border-slate-300 dark:border-slate-600"
                />
                <div>
                  <span className="text-sm text-slate-700 dark:text-slate-300">Stop queue on cookie expiration</span>
                  <p className="text-xs text-slate-500 dark:text-slate-400">
                    When enabled, the queue will stop processing and requeue the current item if cookies expire
                  </p>
                </div>
              </label>

              <label className="flex items-center space-x-3 cursor-pointer">
                <input
                  type="checkbox"
                  checked={queueSettings.send_cookie_notification !== false}
                  onChange={(e) => updateQueueSettings({ send_cookie_notification: e.target.checked })}
                  className="w-4 h-4 rounded border-slate-300 dark:border-slate-600"
                />
                <div>
                  <span className="text-sm text-slate-700 dark:text-slate-300">Send push notification</span>
                  <p className="text-xs text-slate-500 dark:text-slate-400">
                    Send a Pushover notification when cookies expire (requires Pushover to be configured)
                  </p>
                </div>
              </label>

              <label className="flex items-center space-x-3 cursor-pointer">
                <input
                  type="checkbox"
                  checked={queueSettings.auto_start_on_restart === true}
                  onChange={(e) => updateQueueSettings({ auto_start_on_restart: e.target.checked })}
                  className="w-4 h-4 rounded border-slate-300 dark:border-slate-600"
                />
                <div>
                  <span className="text-sm text-slate-700 dark:text-slate-300">Auto-start queue on API restart</span>
                  <p className="text-xs text-slate-500 dark:text-slate-400">
                    Automatically resume downloading when the API restarts (continues from where it left off)
                  </p>
                </div>
              </label>
            </div>
          </div>

          <div className="flex justify-end">
            <button
              onClick={handleSaveQueueSettings}
              disabled={updateQueueMutation.isPending}
              className="flex items-center space-x-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white rounded-lg transition-colors"
            >
              {updateQueueMutation.isPending ? (
                <Loader2 className="w-4 h-4 animate-spin" />
              ) : (
                <Save className="w-4 h-4" />
              )}
              <span>Save Queue Settings</span>
            </button>
          </div>
        </div>
      </div>

      {/* Anti-Bot Protection */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100 flex items-center space-x-2">
            <Shield className="w-5 h-5" />
            <span>Anti-Bot Protection</span>
          </h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={antibotSettings.enabled !== false}
              onChange={(e) => updateAntibotSettingsState({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          Configure yt-dlp settings to avoid detection and throttling by YouTube and other platforms.
        </p>

        {antibotSettings.enabled !== false && (
          <div className="space-y-4">
            {/* Browser / User Agent */}
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Browser User-Agent
              </label>
              <select
                value={antibotSettings.browser || 'edge'}
                onChange={(e) => updateAntibotSettingsState({ browser: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              >
                <option value="edge">Microsoft Edge</option>
                <option value="chrome">Google Chrome</option>
                <option value="firefox">Mozilla Firefox</option>
                <option value="safari">Safari</option>
                <option value="custom">Custom User-Agent</option>
              </select>
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Select the browser that matches your exported cookies to avoid session invalidation.
              </p>
            </div>

            {/* Custom User Agent */}
            {antibotSettings.browser === 'custom' && (
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Custom User-Agent String
                </label>
                <input
                  type="text"
                  value={antibotSettings.custom_user_agent || ''}
                  onChange={(e) => updateAntibotSettingsState({ custom_user_agent: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
                  placeholder="Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
                />
              </div>
            )}

            {/* Rate Limiting */}
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Download Rate Limit
                </label>
                <input
                  type="text"
                  value={antibotSettings.limit_rate || '2M'}
                  onChange={(e) => updateAntibotSettingsState({ limit_rate: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  placeholder="2M"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  Max download speed (e.g., 2M, 500K). Prevents bandwidth spikes.
                </p>
              </div>

              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Throttle Detection Rate
                </label>
                <input
                  type="text"
                  value={antibotSettings.throttled_rate || '100K'}
                  onChange={(e) => updateAntibotSettingsState({ throttled_rate: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  placeholder="100K"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  Restart if speed drops below this (detects throttling).
                </p>
              </div>
            </div>

            {/* Sleep Between Requests */}
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Min Sleep Between Requests (sec)
                </label>
                <input
                  type="number"
                  min="0"
                  max="30"
                  value={antibotSettings.sleep_requests_min ?? 1}
                  onChange={(e) => updateAntibotSettingsState({ sleep_requests_min: parseInt(e.target.value) || 0 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Max Sleep Between Requests (sec)
                </label>
                <input
                  type="number"
                  min="0"
                  max="30"
                  value={antibotSettings.sleep_requests_max ?? 3}
                  onChange={(e) => updateAntibotSettingsState({ sleep_requests_max: parseInt(e.target.value) || 0 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
            </div>
            <p className="text-xs text-slate-500 dark:text-slate-400 -mt-2">
              Random delay between HTTP requests to mimic human browsing behavior.
            </p>

            {/* Retries and Fragments */}
            <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Retries
                </label>
                <input
                  type="number"
                  min="1"
                  max="50"
                  value={antibotSettings.retries ?? 10}
                  onChange={(e) => updateAntibotSettingsState({ retries: parseInt(e.target.value) || 10 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Fragment Retries
                </label>
                <input
                  type="number"
                  min="1"
                  max="50"
                  value={antibotSettings.fragment_retries ?? 10}
                  onChange={(e) => updateAntibotSettingsState({ fragment_retries: parseInt(e.target.value) || 10 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Concurrent Fragments
                </label>
                <input
                  type="number"
                  min="1"
                  max="10"
                  value={antibotSettings.concurrent_fragments ?? 1}
                  onChange={(e) => updateAntibotSettingsState({ concurrent_fragments: parseInt(e.target.value) || 1 })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
              </div>
            </div>

            {/* Socket Timeout */}
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Socket Timeout (seconds)
              </label>
              <input
                type="number"
                min="10"
                max="120"
                value={antibotSettings.socket_timeout ?? 30}
                onChange={(e) => updateAntibotSettingsState({ socket_timeout: parseInt(e.target.value) || 30 })}
                className="w-24 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Connection timeout to prevent stuck downloads.
              </p>
            </div>

            <div className="p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
              <p className="text-xs text-blue-700 dark:text-blue-300">
                <strong>Tip:</strong> These settings help avoid YouTube's bot detection. The default values work well for most cases. Lower rate limits and longer sleep intervals are safer but slower.
              </p>
            </div>

            <div className="flex justify-end">
              <button
                onClick={handleSaveAntibotSettings}
                disabled={updateAntibotMutation.isPending}
                className="flex items-center space-x-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white rounded-lg transition-colors"
              >
                {updateAntibotMutation.isPending ? (
                  <Loader2 className="w-4 h-4 animate-spin" />
                ) : (
                  <Save className="w-4 h-4" />
                )}
                <span>Save Anti-Bot Settings</span>
              </button>
            </div>
          </div>
        )}
      </div>

      {/* Easynews Settings */}
      <EasynewsConfigSection />

      {/* Immich Integration */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Immich Integration</h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={immichSettings.enabled || false}
              onChange={(e) => updateImmichSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        {immichSettings.enabled && (
          <div className="space-y-3">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                API URL
              </label>
              <input
                type="text"
                value={immichSettings.api_url || ''}
                onChange={(e) => updateImmichSettings({ api_url: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                placeholder="http://192.168.1.6:2283/api"
              />
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                API Key
              </label>
              <input
                type="password"
                value={immichSettings.api_key || ''}
                onChange={(e) => updateImmichSettings({ api_key: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                placeholder="Enter your Immich API key"
              />
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Library ID
              </label>
              <input
                type="text"
                value={immichSettings.library_id || ''}
                onChange={(e) => updateImmichSettings({ library_id: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                placeholder="ec75af9d-7ce2-48a8-85c1-e20b69da20ed"
              />
            </div>
            <div className="flex flex-col space-y-2">
              <label className="flex items-center space-x-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={immichSettings.scan_after_download || false}
                  onChange={(e) => updateImmichSettings({ scan_after_download: e.target.checked })}
                  className="w-4 h-4 rounded"
                />
                <span className="text-sm text-slate-600 dark:text-slate-400">Scan after each download</span>
              </label>
              <label className="flex items-center space-x-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={immichSettings.scan_at_end || false}
                  onChange={(e) => updateImmichSettings({ scan_at_end: e.target.checked })}
                  className="w-4 h-4 rounded"
                />
                <span className="text-sm text-slate-600 dark:text-slate-400">Scan at end of all downloads</span>
              </label>
            </div>
          </div>
        )}
      </div>

      {/* Instagram Repost Detection */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Instagram Repost Detection</h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={repostDetectionSettings.enabled || false}
              onChange={(e) => updateRepostDetectionSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          Automatically detect when Instagram stories are reposts/screenshots of other users' content and replace with high-quality originals. Uses OCR to detect @username, downloads that user's content, and uses perceptual hash matching to find the original. Processing happens after batch completion to avoid blocking the download pipeline.
        </p>
        {repostDetectionSettings.enabled && (
          <div className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Hash Distance Threshold (0-64)
              </label>
              <input
                type="number"
                min="0"
                max="64"
                value={repostDetectionSettings.hash_distance_threshold || 10}
                onChange={(e) => updateRepostDetectionSettings({ hash_distance_threshold: parseInt(e.target.value) })}
                className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Lower = stricter matching (default: 10). How similar images must be to match.
              </p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Fetch Cache Duration (hours)
              </label>
              <input
                type="number"
                min="1"
                max="48"
                value={repostDetectionSettings.fetch_cache_hours || 12}
                onChange={(e) => updateRepostDetectionSettings({ fetch_cache_hours: parseInt(e.target.value) })}
                className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                How long to cache original user's content before re-downloading (default: 12 hours)
              </p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Max Posts Age (hours)
              </label>
              <input
                type="number"
                min="1"
                max="72"
                value={repostDetectionSettings.max_posts_age_hours || 24}
                onChange={(e) => updateRepostDetectionSettings({ max_posts_age_hours: parseInt(e.target.value) })}
                className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                How far back to check original user's posts (default: 24 hours)
              </p>
            </div>
            <div className="p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
              <p className="text-xs text-blue-700 dark:text-blue-300">
                <strong>Note:</strong> All repost sources (monitored or not) are saved permanently and processed through face recognition. This ensures you capture all available content and multiple images from discovered accounts.
              </p>
            </div>
          </div>
        )}
      </div>

      {/* Instagram Perceptual Duplicate Detection */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Instagram Perceptual Duplicate Detection</h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={instagramPerceptualDuplicatesSettings.enabled || false}
              onChange={(e) => updateInstagramPerceptualDuplicatesSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          Detects visually similar Instagram content even with text overlays, stickers, or filters. Keeps the cleanest + highest quality version. Prioritizes clean (no overlays) over quality.
        </p>
        {instagramPerceptualDuplicatesSettings.enabled && (
          <div className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Perceptual Hash Threshold (0-64)
              </label>
              <input
                type="number"
                min="0"
                max="64"
                value={instagramPerceptualDuplicatesSettings.perceptual_hash_threshold || 12}
                onChange={(e) => updateInstagramPerceptualDuplicatesSettings({ perceptual_hash_threshold: parseInt(e.target.value) })}
                className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Lower = stricter matching (default: 12). How similar images must be to be considered duplicates.
              </p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Clean Score Weight vs Quality Score Weight
              </label>
              <div className="flex items-center space-x-4">
                <div>
                  <label className="text-xs text-slate-600 dark:text-slate-400">Clean</label>
                  <input
                    type="number"
                    min="1"
                    max="10"
                    value={instagramPerceptualDuplicatesSettings.clean_score_weight || 3}
                    onChange={(e) => updateInstagramPerceptualDuplicatesSettings({ clean_score_weight: parseInt(e.target.value) })}
                    className="w-20 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  />
                </div>
                <span className="text-slate-600 dark:text-slate-400">:</span>
                <div>
                  <label className="text-xs text-slate-600 dark:text-slate-400">Quality</label>
                  <input
                    type="number"
                    min="1"
                    max="10"
                    value={instagramPerceptualDuplicatesSettings.quality_score_weight || 1}
                    onChange={(e) => updateInstagramPerceptualDuplicatesSettings({ quality_score_weight: parseInt(e.target.value) })}
                    className="w-20 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  />
                </div>
              </div>
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                How much to prioritize clean content over quality (default: 3:1 - clean is 3x more important)
              </p>
            </div>
            <div>
              <label className="flex items-center space-x-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={instagramPerceptualDuplicatesSettings.text_detection_enabled !== false}
                  onChange={(e) => updateInstagramPerceptualDuplicatesSettings({ text_detection_enabled: e.target.checked })}
                  className="w-4 h-4 rounded"
                />
                <span className="text-sm text-slate-600 dark:text-slate-400">Enable text overlay detection (OCR)</span>
              </label>
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Use OCR to detect text overlays and prefer versions with less text (recommended)
              </p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Minimum Text Difference
              </label>
              <input
                type="number"
                min="1"
                max="20"
                value={instagramPerceptualDuplicatesSettings.min_text_difference || 5}
                onChange={(e) => updateInstagramPerceptualDuplicatesSettings({ min_text_difference: parseInt(e.target.value) })}
                className="w-32 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Minimum score difference to consider one file cleaner (default: 5)
              </p>
            </div>
          </div>
        )}
      </div>

      {/* File Ownership */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">File Ownership</h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={fileOwnershipSettings.enabled || false}
              onChange={(e) => updateFileOwnershipSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          Automatically change file ownership after moving files (requires sudo/root permissions).
        </p>
        {fileOwnershipSettings.enabled && (
          <div className="space-y-4">
            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Owner (username)
                </label>
                <input
                  type="text"
                  value={fileOwnershipSettings.owner || ''}
                  onChange={(e) => updateFileOwnershipSettings({ owner: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  placeholder="wkastner"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  System username to own the files
                </p>
              </div>
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Group (group name)
                </label>
                <input
                  type="text"
                  value={fileOwnershipSettings.group || ''}
                  onChange={(e) => updateFileOwnershipSettings({ group: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  placeholder="wkastner"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  System group to own the files
                </p>
              </div>
            </div>
            <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3">
              <p className="text-xs text-blue-800 dark:text-blue-300">
                <strong>Note:</strong> The media-downloader service must run with sudo privileges to change file ownership.
                Files will be set to the specified owner:group after being moved to their destination.
              </p>
            </div>
          </div>
        )}
      </div>

      {/* Pushover Notifications */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Pushover Notifications</h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={pushoverSettings.enabled || false}
              onChange={(e) => updatePushoverSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        {pushoverSettings.enabled && (
          <div className="space-y-4">
            <div className="grid grid-cols-2 gap-4">
              <div>
                <label htmlFor="pushover-user-key" className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  User Key
                </label>
                <input
                  id="pushover-user-key"
                  name="pushover-user-key"
                  type="text"
                  autoComplete="off"
                  value={pushoverSettings.user_key || ''}
                  onChange={(e) => updatePushoverSettings({ user_key: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
                  placeholder="Your Pushover user key"
                />
              </div>
              <div>
                <label htmlFor="pushover-api-token" className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  API Token
                </label>
                <input
                  id="pushover-api-token"
                  name="pushover-api-token"
                  type="text"
                  autoComplete="off"
                  value={pushoverSettings.api_token || ''}
                  onChange={(e) => updatePushoverSettings({ api_token: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
                  placeholder="Your application API token"
                />
              </div>
            </div>

            {/* Warning if user_key and api_token are identical */}
            {pushoverSettings.user_key && pushoverSettings.api_token &&
             pushoverSettings.user_key === pushoverSettings.api_token && (
              <div className="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-3">
                <div className="flex items-center gap-2 text-amber-800 dark:text-amber-200">
                  <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
                  </svg>
                  <span className="font-medium">Warning: User Key and API Token are identical!</span>
                </div>
                <p className="mt-1 text-sm text-amber-700 dark:text-amber-300">
                  These should be different values. This may have been caused by browser autocomplete. Please verify your Pushover credentials.
                </p>
              </div>
            )}

            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Priority
                </label>
                <select
                  value={pushoverSettings.priority || 0}
                  onChange={(e) => updatePushoverSettings({ priority: parseInt(e.target.value) })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                >
                  <option value="-2">Lowest</option>
                  <option value="-1">Low (No Sound)</option>
                  <option value="0">Normal</option>
                  <option value="1">High</option>
                  <option value="2">Emergency (requires acknowledgment)</option>
                </select>
              </div>
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Sound
                </label>
                <select
                  value={pushoverSettings.sound || 'pushover'}
                  onChange={(e) => updatePushoverSettings({ sound: e.target.value })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                >
                  <option value="pushover">Pushover (default)</option>
                  <option value="bike">Bike</option>
                  <option value="bugle">Bugle</option>
                  <option value="cashregister">Cash Register</option>
                  <option value="classical">Classical</option>
                  <option value="cosmic">Cosmic</option>
                  <option value="falling">Falling</option>
                  <option value="gamelan">Gamelan</option>
                  <option value="incoming">Incoming</option>
                  <option value="intermission">Intermission</option>
                  <option value="magic">Magic</option>
                  <option value="mechanical">Mechanical</option>
                  <option value="pianobar">Piano Bar</option>
                  <option value="siren">Siren</option>
                  <option value="spacealarm">Space Alarm</option>
                  <option value="tugboat">Tug Boat</option>
                  <option value="alien">Alien Alarm (long)</option>
                  <option value="climb">Climb (long)</option>
                  <option value="persistent">Persistent (long)</option>
                  <option value="echo">Echo (long)</option>
                  <option value="updown">Up Down (long)</option>
                  <option value="vibrate">Vibrate Only</option>
                  <option value="none">None (silent)</option>
                </select>
              </div>
            </div>

            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Device (optional)
              </label>
              <input
                type="text"
                value={pushoverSettings.device || ''}
                onChange={(e) => updatePushoverSettings({ device: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                placeholder="Leave blank for all devices or specify device name"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Send to specific device only (e.g., "iphone", "android"). Leave blank to send to all devices.
              </p>
            </div>

            <label className="flex items-center space-x-2 cursor-pointer">
              <input
                type="checkbox"
                checked={pushoverSettings.include_image || false}
                onChange={(e) => updatePushoverSettings({ include_image: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <div>
                <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Include image in notifications</span>
                <p className="text-xs text-slate-500 dark:text-slate-400">Attach thumbnail images to download notifications when available</p>
              </div>
            </label>

            <label className="flex items-center space-x-2 cursor-pointer">
              <input
                type="checkbox"
                checked={pushoverSettings.enable_review_queue_notifications !== false}
                onChange={(e) => updatePushoverSettings({ enable_review_queue_notifications: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <div>
                <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enable Review Queue Push Notifications</span>
                <p className="text-xs text-slate-500 dark:text-slate-400">Send push notifications for items moved to review queue (no face match detected)</p>
              </div>
            </label>
          </div>
        )}
      </div>

      {/* Recycle Bin */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100 flex items-center space-x-2">
            <Trash2 className="w-5 h-5" />
            <span>Recycle Bin</span>
          </h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={recycleBinSettings.enabled !== false}
              onChange={(e) => updateRecycleBinSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          Soft-delete files to recycle bin instead of permanent deletion. Files can be restored or permanently deleted from the Recycle Bin page.
        </p>
        {recycleBinSettings.enabled !== false && (
          <div className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Recycle Bin Path
              </label>
              <input
                type="text"
                value={recycleBinSettings.path || '/opt/immich/recycle'}
                onChange={(e) => updateRecycleBinSettings({ path: e.target.value })}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                placeholder="/opt/immich/recycle"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                Directory where deleted files are stored
              </p>
            </div>

            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Retention Days
                </label>
                <input
                  type="number"
                  min="1"
                  max="365"
                  value={recycleBinSettings.retention_days || 30}
                  onChange={(e) => updateRecycleBinSettings({ retention_days: parseInt(e.target.value) })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  Files older than this are auto-deleted (1-365 days)
                </p>
              </div>

              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Max Size (GB)
                </label>
                <input
                  type="number"
                  min="1"
                  max="1000"
                  value={recycleBinSettings.max_size_gb || 50}
                  onChange={(e) => updateRecycleBinSettings({ max_size_gb: parseInt(e.target.value) })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  Maximum storage for recycle bin (1-1000 GB)
                </p>
              </div>
            </div>

            <label className="flex items-center space-x-2 cursor-pointer">
              <input
                type="checkbox"
                checked={recycleBinSettings.auto_cleanup !== false}
                onChange={(e) => updateRecycleBinSettings({ auto_cleanup: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <div>
                <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Auto-cleanup enabled</span>
                <p className="text-xs text-slate-500 dark:text-slate-400">
                  Automatically delete files older than retention period
                </p>
              </div>
            </label>
          </div>
        )}
      </div>

      <button
        onClick={handleSave}
        disabled={updateMutation.isPending}
        className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded-lg transition-colors flex items-center space-x-2"
      >
        <Save className="w-4 h-4" />
        <span>Save Download Settings</span>
      </button>
    </div>
  )
}

// Manual Import Tab
function ManualImportTab() {
  const queryClient = useQueryClient()
  const [config, setConfig] = useState<any>(null)
  const [editingService, setEditingService] = useState<any>(null)
  const [showAddService, setShowAddService] = useState(false)
  const [presetPatterns, setPresetPatterns] = useState<Record<string, any>>({})

  const { isLoading } = useQuery({
    queryKey: ['settings', 'manual_import'],
    queryFn: async () => {
      const response = await api.getManualImportServices() as any
      setConfig(response)
      if (response.preset_patterns) {
        setPresetPatterns(response.preset_patterns)
      }
      return response
    },
  })

  const saveMutation = useMutation({
    mutationFn: async (newConfig: any) => api.updateSetting('manual_import', newConfig),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['settings', 'manual_import'] })
      queryClient.invalidateQueries({ queryKey: ['manual-import-services'] })
      notificationManager.settingsSaved('Manual Import')
    },
    onError: (err: unknown) => notificationManager.settingsSaveError(err, 'Manual Import')
  })

  const handleAddService = (service: any) => {
    const updated = { ...config, enabled: true, services: [...(config?.services || []), service] }
    setConfig(updated)
    saveMutation.mutate(updated)
    setShowAddService(false)
  }

  const handleUpdateService = (index: number, service: any) => {
    const updated = {
      ...config,
      enabled: true,
      services: config.services.map((s: any, i: number) => i === index ? service : s)
    }
    setConfig(updated)
    saveMutation.mutate(updated)
    setEditingService(null)
  }

  const handleDeleteService = (index: number) => {
    if (!confirm('Delete this service?')) return
    const services = config.services.filter((_: any, i: number) => i !== index)
    const updated = { ...config, enabled: services.length > 0, services }
    setConfig(updated)
    saveMutation.mutate(updated)
  }

  const handleToggleServiceEnabled = (index: number) => {
    const updated = {
      ...config,
      services: config.services.map((s: any, i: number) =>
        i === index ? { ...s, enabled: !s.enabled } : s
      )
    }
    setConfig(updated)
    saveMutation.mutate(updated)
  }

  if (isLoading || !config) {
    return <div className="animate-pulse h-48 bg-slate-100 dark:bg-slate-700 rounded" />
  }

  const getPlatformIcon = (platform: string) => {
    const icons: Record<string, string> = {
      instagram: '📷', tiktok: '🎵', youtube: '▶️', snapchat: '👻', twitter: '🐦', reddit: '🔴'
    }
    return icons[platform] || '📁'
  }

  return (
    <div className="space-y-6">
      <div>
        <h2 className="text-xl font-semibold text-slate-900 dark:text-slate-100">Manual Import</h2>
        <p className="text-sm text-slate-500 dark:text-slate-400 mt-1">
          Upload and import media files with automatic metadata extraction
        </p>
      </div>

      {/* Services Grid */}
      <div>
        <div className="flex justify-between items-center mb-4">
          <h3 className="text-lg font-medium dark:text-white">Import Services</h3>
          <button
            onClick={() => setShowAddService(true)}
            className="flex items-center gap-2 px-3 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
          >
            <Plus className="w-4 h-4" />
            Add Service
          </button>
        </div>

        {(!config?.services || config.services.length === 0) ? (
          <div className="card-glass text-center py-12 rounded-xl border-2 border-dashed border-slate-200 dark:border-slate-700">
            <Upload className="w-12 h-12 text-slate-400 mx-auto mb-3" />
            <p className="text-slate-600 dark:text-slate-300 font-medium">No import services configured</p>
            <p className="text-sm text-slate-500 dark:text-slate-400 mt-1 mb-4">
              Add a service to start importing files from different platforms
            </p>
            <button
              onClick={() => setShowAddService(true)}
              className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
            >
              Add Your First Service
            </button>
          </div>
        ) : (
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            {config.services.map((service: any, index: number) => (
              <div
                key={index}
                className={`card-glass p-4 rounded-xl transition-all ${
                  service.enabled
                    ? ''
                    : 'opacity-60'
                }`}
              >
                <div className="flex items-start justify-between mb-3">
                  <div className="flex items-center gap-3">
                    <span className="text-2xl">{getPlatformIcon(service.platform)}</span>
                    <div>
                      <h4 className="font-semibold dark:text-white">{service.name}</h4>
                      <div className="flex items-center gap-2 mt-0.5">
                        <span className="text-xs px-2 py-0.5 bg-slate-100 dark:bg-slate-700 rounded capitalize">
                          {service.platform}
                        </span>
                        {service.use_ytdlp && (
                          <span className="text-xs px-2 py-0.5 bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400 rounded">
                            yt-dlp
                          </span>
                        )}
                      </div>
                    </div>
                  </div>
                  <button
                    onClick={() => handleToggleServiceEnabled(index)}
                    className={`w-10 h-6 rounded-full transition-colors relative ${
                      service.enabled ? 'bg-green-500' : 'bg-slate-300 dark:bg-slate-600'
                    }`}
                  >
                    <span className={`absolute top-1 w-4 h-4 bg-white rounded-full transition-transform ${
                      service.enabled ? 'left-5' : 'left-1'
                    }`} />
                  </button>
                </div>

                <div className="text-sm text-slate-500 dark:text-slate-400 space-y-1 mb-3">
                  <div className="truncate" title={service.destination}>
                    <span className="text-slate-400 dark:text-slate-500">→</span> {service.destination}
                  </div>
                  {service.parse_filename && (
                    <div className="font-mono text-xs bg-slate-100 dark:bg-slate-700 px-2 py-1 rounded truncate">
                      {service.filename_pattern}
                    </div>
                  )}
                </div>

                <div className="flex gap-2 pt-2 border-t border-slate-100 dark:border-slate-700">
                  <button
                    onClick={() => setEditingService({ index, ...service })}
                    className="flex-1 py-1.5 text-sm text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded transition-colors"
                  >
                    Edit
                  </button>
                  <button
                    onClick={() => handleDeleteService(index)}
                    className="flex-1 py-1.5 text-sm text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors"
                  >
                    Delete
                  </button>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Add/Edit Service Modal */}
      {(showAddService || editingService) && (
        <ImportServiceModal
          service={editingService}
          presetPatterns={presetPatterns}
          onSave={(service) => {
            if (editingService) {
              handleUpdateService(editingService.index, service)
            } else {
              handleAddService(service)
            }
          }}
          onClose={() => {
            setShowAddService(false)
            setEditingService(null)
          }}
        />
      )}
    </div>
  )
}

// Import Service Add/Edit Modal - Clean & Simple
function ImportServiceModal({
  service,
  presetPatterns,
  onSave,
  onClose
}: {
  service: any
  presetPatterns: Record<string, any>
  onSave: (service: any) => void
  onClose: () => void
}) {
  const [step, setStep] = useState(service ? 2 : 1) // Step 1: Select preset, Step 2: Configure
  const [form, setForm] = useState({
    name: service?.name || '',
    platform: service?.platform || '',
    content_type: service?.content_type || 'photos',
    filename_pattern: service?.filename_pattern || '',
    destination: service?.destination || '',
    enabled: service?.enabled !== false,
    parse_filename: service?.parse_filename !== false,
    use_ytdlp: service?.use_ytdlp || false
  })
  const [showAdvanced, setShowAdvanced] = useState(false)

  const handleSelectPreset = (key: string) => {
    const preset = presetPatterns[key]
    if (!preset) return

    const platform = preset.platform || 'other'
    const contentType = preset.content_type || 'photos'

    setForm({
      name: preset.name,
      platform,
      content_type: contentType,
      filename_pattern: preset.pattern,
      destination: platform === 'youtube'
        ? '/opt/immich/md/youtube'
        : `/opt/immich/md/social media/${platform}/${contentType}`,
      enabled: true,
      parse_filename: !preset.use_ytdlp,
      use_ytdlp: preset.use_ytdlp || false
    })
    setStep(2)
  }

  const handleSubmit = () => {
    if (!form.name || !form.destination) {
      notificationManager.validationError('Name and destination are required')
      return
    }
    // If parse_filename is enabled, require a pattern
    if (form.parse_filename && !form.filename_pattern) {
      notificationManager.validationError('Filename pattern is required when auto-parse is enabled')
      return
    }
    onSave(form)
  }

  const presetGroups = {
    instagram: Object.entries(presetPatterns).filter(([_, p]) => p.platform === 'instagram'),
    youtube: Object.entries(presetPatterns).filter(([_, p]) => p.platform === 'youtube'),
    other: Object.entries(presetPatterns).filter(([_, p]) => !['instagram', 'youtube'].includes(p.platform))
  }

  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
      <div className="bg-white dark:bg-slate-800 rounded-xl shadow-2xl max-w-xl w-full max-h-[85vh] overflow-hidden flex flex-col">
        {/* Header */}
        <div className="flex justify-between items-center px-6 py-4 border-b dark:border-slate-700">
          <h3 className="text-lg font-semibold dark:text-white">
            {service ? 'Edit Import Service' : step === 1 ? 'Choose Service Type' : 'Configure Service'}
          </h3>
          <button onClick={onClose} className="p-1 hover:bg-slate-100 dark:hover:bg-slate-700 rounded">
            <X className="w-5 h-5 text-slate-500" />
          </button>
        </div>

        {/* Content */}
        <div className="flex-1 overflow-y-auto custom-scrollbar p-6">
          {step === 1 ? (
            /* Step 1: Preset Selection */
            <div className="space-y-6">
              {/* Instagram */}
              {presetGroups.instagram.length > 0 && (
                <div>
                  <h4 className="text-sm font-medium text-slate-500 dark:text-slate-400 mb-3 flex items-center gap-2">
                    <span className="text-lg">📷</span> Instagram
                  </h4>
                  <div className="grid grid-cols-1 gap-2">
                    {presetGroups.instagram.map(([key, preset]) => (
                      <button
                        key={key}
                        onClick={() => handleSelectPreset(key)}
                        className="p-4 text-left rounded-lg border-2 border-slate-200 dark:border-slate-600 hover:border-blue-500 dark:hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all"
                      >
                        <div className="font-medium dark:text-white">{preset.name}</div>
                        <div className="text-sm text-slate-500 dark:text-slate-400 mt-1 font-mono">{preset.example}</div>
                      </button>
                    ))}
                  </div>
                </div>
              )}

              {/* YouTube */}
              {presetGroups.youtube.length > 0 && (
                <div>
                  <h4 className="text-sm font-medium text-slate-500 dark:text-slate-400 mb-3 flex items-center gap-2">
                    <span className="text-lg">▶️</span> YouTube
                  </h4>
                  <div className="grid grid-cols-1 gap-2">
                    {presetGroups.youtube.map(([key, preset]) => (
                      <button
                        key={key}
                        onClick={() => handleSelectPreset(key)}
                        className="p-4 text-left rounded-lg border-2 border-slate-200 dark:border-slate-600 hover:border-blue-500 dark:hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all"
                      >
                        <div className="font-medium dark:text-white flex items-center gap-2">
                          {preset.name}
                          {preset.use_ytdlp && (
                            <span className="text-xs px-2 py-0.5 bg-red-100 dark:bg-red-900/30 text-red-600 rounded">yt-dlp</span>
                          )}
                        </div>
                        <div className="text-sm text-slate-500 dark:text-slate-400 mt-1">Auto-fetches metadata from YouTube</div>
                      </button>
                    ))}
                  </div>
                </div>
              )}

              {/* Other */}
              {presetGroups.other.length > 0 && (
                <div>
                  <h4 className="text-sm font-medium text-slate-500 dark:text-slate-400 mb-3 flex items-center gap-2">
                    <span className="text-lg">📱</span> Other Platforms
                  </h4>
                  <div className="grid grid-cols-1 gap-2">
                    {presetGroups.other.map(([key, preset]) => (
                      <button
                        key={key}
                        onClick={() => handleSelectPreset(key)}
                        className="p-4 text-left rounded-lg border-2 border-slate-200 dark:border-slate-600 hover:border-blue-500 dark:hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all"
                      >
                        <div className="font-medium dark:text-white">{preset.name}</div>
                        <div className="text-sm text-slate-500 dark:text-slate-400 mt-1 font-mono">{preset.example}</div>
                      </button>
                    ))}
                  </div>
                </div>
              )}

              {/* Custom */}
              <div>
                <h4 className="text-sm font-medium text-slate-500 dark:text-slate-400 mb-3 flex items-center gap-2">
                  <span className="text-lg">⚙️</span> Custom
                </h4>
                <button
                  onClick={() => setStep(2)}
                  className="w-full p-4 text-left rounded-lg border-2 border-dashed border-slate-300 dark:border-slate-600 hover:border-blue-500 dark:hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all"
                >
                  <div className="font-medium dark:text-white">Create Custom Service</div>
                  <div className="text-sm text-slate-500 dark:text-slate-400 mt-1">Define your own filename pattern and settings</div>
                </button>
              </div>
            </div>
          ) : (
            /* Step 2: Configuration */
            <div className="space-y-4">
              {/* Service Name */}
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5">
                  Service Name
                </label>
                <input
                  type="text"
                  value={form.name}
                  onChange={(e) => setForm(prev => ({ ...prev, name: e.target.value }))}
                  placeholder="e.g., Instagram Stories"
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-white"
                />
              </div>

              {/* Destination */}
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5">
                  Destination Folder
                </label>
                <input
                  type="text"
                  value={form.destination}
                  onChange={(e) => setForm(prev => ({ ...prev, destination: e.target.value }))}
                  placeholder="/opt/immich/md/..."
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-white font-mono text-sm"
                />
              </div>

              {/* Parse Filename Toggle */}
              <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-700/50 rounded-lg">
                <div>
                  <span className="font-medium text-sm dark:text-white">Auto-parse filenames</span>
                  <p className="text-xs text-slate-500 dark:text-slate-400">
                    Extract date/time from filename pattern
                  </p>
                </div>
                <button
                  type="button"
                  onClick={() => setForm(prev => ({ ...prev, parse_filename: !prev.parse_filename }))}
                  className={`w-11 h-6 rounded-full transition-colors relative ${
                    form.parse_filename ? 'bg-blue-600' : 'bg-slate-300 dark:bg-slate-600'
                  }`}
                >
                  <span className={`absolute top-1 w-4 h-4 bg-white rounded-full transition-all ${
                    form.parse_filename ? 'left-6' : 'left-1'
                  }`} />
                </button>
              </div>

              {/* Advanced Settings Toggle */}
              <button
                type="button"
                onClick={() => setShowAdvanced(!showAdvanced)}
                className="w-full py-2 text-sm text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white flex items-center justify-center gap-1"
              >
                {showAdvanced ? '▲ Hide' : '▼ Show'} Advanced Settings
              </button>

              {showAdvanced && (
                <div className="space-y-4 pt-2 border-t border-slate-200 dark:border-slate-700">
                  {/* Platform */}
                  <div>
                    <label className="block text-xs font-medium text-slate-600 dark:text-slate-400 mb-1">Platform</label>
                    <select
                      value={form.platform}
                      onChange={(e) => setForm(prev => ({ ...prev, platform: e.target.value }))}
                      className="w-full px-2 py-1.5 text-sm border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 dark:text-white"
                    >
                      <option value="instagram">Instagram</option>
                      <option value="tiktok">TikTok</option>
                      <option value="youtube">YouTube</option>
                      <option value="snapchat">Snapchat</option>
                      <option value="twitter">Twitter/X</option>
                      <option value="other">Other</option>
                    </select>
                  </div>

                  {/* Filename Pattern */}
                  {form.parse_filename && (
                    <div>
                      <label className="block text-xs font-medium text-slate-600 dark:text-slate-400 mb-1">Filename Pattern</label>
                      <input
                        type="text"
                        value={form.filename_pattern}
                        onChange={(e) => setForm(prev => ({ ...prev, filename_pattern: e.target.value }))}
                        className="w-full px-2 py-1.5 text-sm border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 dark:text-white font-mono"
                      />
                      <p className="text-xs text-slate-500 mt-1">
                        Tokens: {'{username}'} {'{YYYYMMDD}'} {'{HHMMSS}'} {'{id}'}
                      </p>
                    </div>
                  )}

                  {/* YouTube yt-dlp */}
                  {form.platform === 'youtube' && (
                    <div className="flex items-center justify-between p-2 bg-red-50 dark:bg-red-900/20 rounded border border-red-200 dark:border-red-800">
                      <span className="text-sm dark:text-white">Use yt-dlp for metadata</span>
                      <button
                        type="button"
                        onClick={() => setForm(prev => ({ ...prev, use_ytdlp: !prev.use_ytdlp }))}
                        className={`w-10 h-5 rounded-full transition-colors relative ${
                          form.use_ytdlp ? 'bg-red-500' : 'bg-slate-300'
                        }`}
                      >
                        <span className={`absolute top-0.5 w-4 h-4 bg-white rounded-full transition-all ${
                          form.use_ytdlp ? 'left-5' : 'left-0.5'
                        }`} />
                      </button>
                    </div>
                  )}
                </div>
              )}
            </div>
          )}
        </div>

        {/* Footer */}
        <div className="px-6 py-4 border-t dark:border-slate-700 flex justify-between">
          {step === 2 && !service && (
            <button
              onClick={() => setStep(1)}
              className="px-4 py-2 text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white"
            >
              ← Back
            </button>
          )}
          <div className="ml-auto flex gap-2">
            <button
              onClick={onClose}
              className="px-4 py-2 text-slate-600 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-700 rounded-lg"
            >
              Cancel
            </button>
            {step === 2 && (
              <button
                onClick={handleSubmit}
                className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
              >
                {service ? 'Save Changes' : 'Add Service'}
              </button>
            )}
          </div>
        </div>
      </div>
    </div>
  )
}

// Monitoring Tab
function MonitoringTab() {
  const [monitoringSettings, setMonitoringSettings] = useState<any>(null)
  const [errorMonitoringSettings, setErrorMonitoringSettings] = useState<any>(null)
  const queryClient = useQueryClient()

  const { isLoading } = useQuery({
    queryKey: ['settings', 'monitoring'],
    queryFn: async () => {
      const response = await api.getSetting('monitoring')
      setMonitoringSettings(response)
      return response
    },
  })

  const { isLoading: isLoadingErrorMonitoring } = useQuery({
    queryKey: ['error-monitoring-settings'],
    queryFn: async () => {
      const response = await api.get('/error-monitoring/settings')
      setErrorMonitoringSettings(response)
      return response
    },
  })

  const updateMutation = useMutation({
    mutationFn: async (newSettings: any) => {
      await api.updateSetting('monitoring', newSettings)
    },
    onSuccess: () => {
      notificationManager.settingsSaved('Monitoring')
      queryClient.invalidateQueries({ queryKey: ['settings', 'monitoring'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Monitoring')
    },
  })

  const updateErrorMonitoringMutation = useMutation({
    mutationFn: async (newSettings: any) => {
      await api.put('/error-monitoring/settings', newSettings)
    },
    onSuccess: () => {
      notificationManager.settingsSaved('Error monitoring')
      queryClient.invalidateQueries({ queryKey: ['error-monitoring-settings'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Error monitoring')
    },
  })

  if (isLoading || isLoadingErrorMonitoring || !monitoringSettings || !errorMonitoringSettings) {
    return <div className="text-center py-8 text-slate-600 dark:text-slate-400">Loading configuration...</div>
  }

  const updateMonitoringSettings = (updates: any) => {
    const updatedSettings = {
      ...monitoringSettings,
      ...updates,
      // Deep merge for nested objects
      ...(updates.pushover && {
        pushover: {
          ...monitoringSettings.pushover,
          ...updates.pushover
        }
      })
    }
    setMonitoringSettings(updatedSettings)
  }

  const updateDownloaderSettings = (downloader: string, enabled: boolean) => {
    const updatedSettings = {
      ...monitoringSettings,
      downloaders: {
        ...monitoringSettings.downloaders,
        [downloader]: enabled
      }
    }
    setMonitoringSettings(updatedSettings)
  }

  const handleSave = () => {
    updateMutation.mutate(monitoringSettings)
  }

  const updateErrorSettings = (updates: any) => {
    setErrorMonitoringSettings((prev: any) => ({
      ...prev,
      ...updates
    }))
  }

  const handleSaveErrorMonitoring = () => {
    updateErrorMonitoringMutation.mutate(errorMonitoringSettings)
  }

  return (
    <div className="space-y-6">
      {/* Monitoring Overview */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Downloader Monitoring</h3>
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={monitoringSettings.enabled || false}
              onChange={(e) => updateMonitoringSettings({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
          </label>
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400">
          Monitor downloader health and send push notifications when a downloader has been failing consistently.
        </p>
      </div>

      {monitoringSettings.enabled && (
        <>
          {/* Alert Configuration */}
          <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
            <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4">Alert Configuration</h3>
            <div className="space-y-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Consecutive Run Failures
                </label>
                <input
                  type="number"
                  min="1"
                  max="10"
                  value={monitoringSettings.min_consecutive_failures || 2}
                  onChange={(e) => updateMonitoringSettings({ min_consecutive_failures: parseInt(e.target.value) })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  Number of consecutive run failures before triggering an alert (e.g., if set to 2, an alert is sent after the service fails 2 times in a row)
                </p>
              </div>
            </div>
          </div>

          {/* Pushover Configuration */}
          <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
            <div className="flex items-center justify-between mb-4">
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Pushover Notifications</h3>
              <label className="flex items-center space-x-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={monitoringSettings.pushover?.enabled || false}
                  onChange={(e) => updateMonitoringSettings({
                    pushover: { ...monitoringSettings.pushover, enabled: e.target.checked }
                  })}
                  className="w-4 h-4 rounded"
                />
                <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
              </label>
            </div>

            {monitoringSettings.pushover?.enabled && (
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Priority Level
                </label>
                <select
                  value={monitoringSettings.pushover?.priority ?? 1}
                  onChange={(e) => updateMonitoringSettings({
                    pushover: { ...monitoringSettings.pushover, priority: parseInt(e.target.value) }
                  })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                >
                  <option value={-2}>Lowest (no notification/alert)</option>
                  <option value={-1}>Low (quiet notification)</option>
                  <option value={0}>Normal</option>
                  <option value={1}>High (bypass quiet hours)</option>
                  <option value={2}>Emergency (requires acknowledgment)</option>
                </select>
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  Notification priority sent to Pushover
                </p>
              </div>
            )}
          </div>

          {/* Per-Downloader Settings */}
          <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
            <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4">Monitored Downloaders</h3>
            <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
              Enable or disable monitoring for individual downloaders
            </p>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
              {Object.entries(monitoringSettings.downloaders || {}).map(([downloader, enabled]) => (
                <label key={downloader} className="flex items-center space-x-2 cursor-pointer p-3 border border-slate-200 dark:border-slate-600 rounded-lg hover:bg-slate-50 dark:hover:bg-slate-700/50">
                  <input
                    type="checkbox"
                    checked={enabled as boolean}
                    onChange={(e) => updateDownloaderSettings(downloader, e.target.checked)}
                    className="w-4 h-4 rounded"
                  />
                  <span className="text-sm text-slate-900 dark:text-slate-100 capitalize">{downloader}</span>
                </label>
              ))}
            </div>
          </div>
        </>
      )}

      <button
        onClick={handleSave}
        disabled={updateMutation.isPending}
        className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded-lg transition-colors flex items-center space-x-2"
      >
        <Save className="w-4 h-4" />
        <span>Save Monitoring Settings</span>
      </button>

      {/* Divider */}
      <div className="border-t border-slate-200 dark:border-slate-700 my-8"></div>

      {/* Error Monitoring Section */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100">Error Monitoring</h3>
          {isLoadingErrorMonitoring ? (
            <span className="text-sm text-slate-500">Loading...</span>
          ) : (
            <label className="flex items-center space-x-2 cursor-pointer">
              <input
                type="checkbox"
                checked={errorMonitoringSettings?.enabled ?? true}
                onChange={(e) => updateErrorSettings({ enabled: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
            </label>
          )}
        </div>
        <p className="text-sm text-slate-600 dark:text-slate-400">
          Monitor application errors and send push notifications when errors remain unreviewed for an extended period.
        </p>
      </div>

      {errorMonitoringSettings?.enabled && (
        <>
          {/* Push Alert Settings */}
          <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
            <div className="flex items-center justify-between mb-4">
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Push Alerts for Errors</h3>
              <label className="flex items-center space-x-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={errorMonitoringSettings?.push_alert_enabled ?? true}
                  onChange={(e) => updateErrorSettings({ push_alert_enabled: e.target.checked })}
                  className="w-4 h-4 rounded"
                />
                <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
              </label>
            </div>

            {errorMonitoringSettings?.push_alert_enabled && (
              <div className="space-y-4">
                <div>
                  <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                    Alert Delay (hours)
                  </label>
                  <input
                    type="number"
                    min="1"
                    max="168"
                    value={errorMonitoringSettings?.push_alert_delay_hours ?? 24}
                    onChange={(e) => updateErrorSettings({ push_alert_delay_hours: parseInt(e.target.value) })}
                    className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                  />
                  <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                    How long an error must remain unreviewed before sending a push notification (default: 24 hours)
                  </p>
                </div>
              </div>
            )}
          </div>

          {/* Dashboard Banner Settings */}
          <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
            <div className="flex items-center justify-between mb-4">
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Dashboard Error Banner</h3>
              <label className="flex items-center space-x-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={errorMonitoringSettings?.dashboard_banner_enabled ?? true}
                  onChange={(e) => updateErrorSettings({ dashboard_banner_enabled: e.target.checked })}
                  className="w-4 h-4 rounded"
                />
                <span className="text-sm text-slate-600 dark:text-slate-400">Enabled</span>
              </label>
            </div>
            <p className="text-sm text-slate-600 dark:text-slate-400">
              Show a banner on the dashboard when there are unreviewed errors
            </p>
          </div>

          {/* Retention Settings */}
          <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
            <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4">Error Log Retention</h3>
            <div className="space-y-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Retention Period (days)
                </label>
                <input
                  type="number"
                  min="1"
                  max="90"
                  value={errorMonitoringSettings?.retention_days ?? 7}
                  onChange={(e) => updateErrorSettings({ retention_days: parseInt(e.target.value) })}
                  className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
                />
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  How long to keep dismissed error logs before automatic cleanup (errors are checked hourly for alerts)
                </p>
              </div>
            </div>
          </div>
        </>
      )}

      <button
        onClick={handleSaveErrorMonitoring}
        disabled={updateErrorMonitoringMutation.isPending || isLoadingErrorMonitoring || !errorMonitoringSettings}
        className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded-lg transition-colors flex items-center space-x-2"
      >
        <Save className="w-4 h-4" />
        <span>Save Error Monitoring Settings</span>
      </button>
    </div>
  )
}

// Dependencies Tab
function DependenciesTab() {
  const [editedConfig, setEditedConfig] = useState<any>(null)
  const queryClient = useQueryClient()

  const { data: _config, isLoading } = useQuery({
    queryKey: ['config'],
    queryFn: async () => {
      const data = await api.getConfig()
      setEditedConfig(data)
      return data
    },
  })

  const updateMutation = useMutation({
    mutationFn: (newConfig: any) => api.updateConfig(newConfig),
    onSuccess: () => {
      notificationManager.settingsSaved('Dependency')
      queryClient.invalidateQueries({ queryKey: ['config'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Dependency')
    },
  })

  const handleSave = () => {
    if (!editedConfig) return
    updateMutation.mutate(editedConfig)
  }

  const updateDependencyUpdater = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      dependency_updater: {
        ...prev?.dependency_updater,
        ...updates
      }
    }))
  }

  const updateComponent = (component: string, updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      dependency_updater: {
        ...prev?.dependency_updater,
        components: {
          ...prev?.dependency_updater?.components,
          [component]: {
            ...prev?.dependency_updater?.components?.[component],
            ...updates
          }
        }
      }
    }))
  }

  const updateOmdb = (updates: any) => {
    setEditedConfig((prev: any) => ({
      ...prev,
      omdb: {
        ...prev?.omdb,
        ...updates
      }
    }))
  }

  if (isLoading || !editedConfig) return <div>Loading...</div>

  const config = editedConfig?.dependency_updater || {}
  const omdbConfig = editedConfig?.omdb || {}

  return (
    <div className="space-y-6">
      <div className="p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
        <h4 className="text-sm font-medium text-blue-900 dark:text-blue-200 mb-2">About Automatic Updates</h4>
        <p className="text-sm text-blue-800 dark:text-blue-300">
          The system automatically checks for updates to critical dependencies (FlareSolverr, Playwright browsers, yt-dlp, and Python packages)
          to ensure optimal performance and security. Updates are checked daily when the scheduler is running and can be installed automatically.
        </p>
      </div>

      {/* Main Settings */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4">General Settings</h3>
        <div className="space-y-4">
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={config.enabled || false}
              onChange={(e) => updateDependencyUpdater({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <div>
              <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enable Automatic Updates</span>
              <p className="text-xs text-slate-500 dark:text-slate-400">Check and install dependency updates automatically</p>
            </div>
          </label>

          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
              Check Interval (hours)
            </label>
            <input
              type="number"
              min="1"
              max="168"
              value={config.check_interval_hours || 24}
              onChange={(e) => updateDependencyUpdater({ check_interval_hours: parseInt(e.target.value) })}
              className="w-40 px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">How often to check for updates (default: 24 hours)</p>
          </div>

          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={config.auto_install !== false}
              onChange={(e) => updateDependencyUpdater({ auto_install: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <div>
              <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Auto-Install Updates</span>
              <p className="text-xs text-slate-500 dark:text-slate-400">Automatically install updates when found (recommended)</p>
            </div>
          </label>
        </div>
      </div>

      {/* OMDB API Settings */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4">OMDB API</h3>
        <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
          OMDB API key is used for TV show date lookups in forum downloads. Get a free API key at{' '}
          <a href="https://www.omdbapi.com/apikey.aspx" target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-700 dark:text-blue-400">
            omdbapi.com
          </a>
        </p>
        <div className="space-y-4">
          <label className="flex items-center space-x-2 cursor-pointer">
            <input
              type="checkbox"
              checked={omdbConfig.enabled !== false}
              onChange={(e) => updateOmdb({ enabled: e.target.checked })}
              className="w-4 h-4 rounded"
            />
            <div>
              <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Enable OMDB Lookups</span>
              <p className="text-xs text-slate-500 dark:text-slate-400">Use OMDB for TV show episode air dates</p>
            </div>
          </label>

          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
              API Key
            </label>
            <input
              type="text"
              value={omdbConfig.api_key || ''}
              onChange={(e) => updateOmdb({ api_key: e.target.value })}
              placeholder="Enter your OMDB API key"
              className="w-full max-w-md px-3 py-2 border border-slate-300 dark:border-slate-600 rounded bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 font-mono text-sm"
            />
            <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
              Your OMDB API key for TV show metadata lookups
            </p>
          </div>
        </div>
      </div>

      {/* Component Settings */}
      <div className="border border-slate-200 dark:border-slate-700 rounded-lg p-4">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-4">Components</h3>
        <div className="space-y-4">
          {[
            { key: 'flaresolverr', name: 'FlareSolverr', desc: 'Docker container for bypassing Cloudflare protection' },
            { key: 'playwright', name: 'Playwright Browsers', desc: 'Chromium and Firefox for browser automation' },
            { key: 'yt_dlp', name: 'yt-dlp', desc: 'YouTube and TikTok downloader (critical for TikTok)' },
            { key: 'python_packages', name: 'Python Packages', desc: 'FastAPI, Uvicorn, Pydantic, and other Python dependencies' }
          ].map((component) => {
            const componentConfig = config.components?.[component.key] || {}
            return (
              <div key={component.key} className="p-3 bg-slate-50 dark:bg-slate-900 rounded-lg">
                <div className="flex items-center justify-between mb-2">
                  <div>
                    <div className="font-medium text-slate-900 dark:text-slate-100">{component.name}</div>
                    <div className="text-xs text-slate-500 dark:text-slate-400">{component.desc}</div>
                  </div>
                </div>
                <div className="flex items-center space-x-4 mt-3">
                  <label className="flex items-center space-x-2 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={componentConfig.enabled !== false}
                      onChange={(e) => updateComponent(component.key, { enabled: e.target.checked })}
                      className="w-4 h-4 rounded"
                    />
                    <span className="text-sm text-slate-600 dark:text-slate-400">Check for updates</span>
                  </label>
                  <label className="flex items-center space-x-2 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={componentConfig.notify_on_update || false}
                      onChange={(e) => updateComponent(component.key, { notify_on_update: e.target.checked })}
                      className="w-4 h-4 rounded"
                    />
                    <span className="text-sm text-slate-600 dark:text-slate-400">Send notification</span>
                  </label>
                </div>
              </div>
            )
          })}
        </div>
      </div>

      <div className="p-4 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg">
        <p className="text-sm text-slate-600 dark:text-slate-400">
          <span className="font-medium">Note:</span> Pushover notifications for dependency updates use the main Pushover settings configured above.
          Use the "Send notification" checkbox for each component to control which updates trigger notifications.
        </p>
      </div>

      <div className="flex justify-end">
        <button
          onClick={handleSave}
          disabled={updateMutation.isPending}
          className="flex items-center space-x-2 px-6 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-slate-400 text-white rounded-lg transition-colors"
        >
          <Save className="w-4 h-4" />
          <span>{updateMutation.isPending ? 'Saving...' : 'Save Configuration'}</span>
        </button>
      </div>
    </div>
  )
}

// Press Tab
function PressTab() {
  const queryClient = useQueryClient()
  const [enabled, setEnabled] = useState(true)
  const [checkIntervalHours, setCheckIntervalHours] = useState(6)
  const [maxRecords, setMaxRecords] = useState(25)
  const [notifyNewArticles, setNotifyNewArticles] = useState(true)
  const [celebrityIds, setCelebrityIds] = useState<number[]>([])
  const [saving, setSaving] = useState(false)

  // Fetch press config
  const { data: pressConfig } = useQuery({
    queryKey: ['press-config'],
    queryFn: () => api.get<{ success: boolean; config: { enabled: boolean; check_interval_hours: number; max_records_per_query: number; notify_new_articles: boolean; celebrity_ids: number[] } }>('/press/config'),
  })

  // Fetch tracked celebrities
  const { data: celebrities } = useQuery({
    queryKey: ['press-celebrities'],
    queryFn: () => api.get<{ success: boolean; celebrities: Array<{ id: number; name: string; slug: string; press_enabled: boolean }> }>('/press/celebrities'),
  })

  // Update state when config loads
  useEffect(() => {
    if (pressConfig?.config) {
      setEnabled(pressConfig.config.enabled)
      setCheckIntervalHours(pressConfig.config.check_interval_hours)
      setMaxRecords(pressConfig.config.max_records_per_query)
      setNotifyNewArticles(pressConfig.config.notify_new_articles)
      setCelebrityIds(pressConfig.config.celebrity_ids || [])
    }
  }, [pressConfig])

  const saveSettings = async () => {
    setSaving(true)
    try {
      await api.put('/press/config', {
        enabled,
        check_interval_hours: checkIntervalHours,
        max_records_per_query: maxRecords,
        notify_new_articles: notifyNewArticles,
      } as Record<string, unknown>)
      notificationManager.success('Press', 'Settings saved')
      queryClient.invalidateQueries({ queryKey: ['press-config'] })
    } catch {
      notificationManager.error('Press', 'Failed to save settings')
    } finally {
      setSaving(false)
    }
  }

  const toggleCelebrity = async (id: number, add: boolean) => {
    const newIds = add
      ? [...celebrityIds, id]
      : celebrityIds.filter(cid => cid !== id)
    setCelebrityIds(newIds)
    try {
      await api.put('/press/config', { celebrity_ids: newIds } as Record<string, unknown>)
      queryClient.invalidateQueries({ queryKey: ['press-config'] })
      queryClient.invalidateQueries({ queryKey: ['press-celebrities'] })
    } catch {
      // Revert on failure
      setCelebrityIds(celebrityIds)
      notificationManager.error('Press', 'Failed to update celebrity selection')
    }
  }

  const celebList = celebrities?.celebrities || []

  return (
    <div className="space-y-6">
      {/* Settings Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-blue-50 to-cyan-50 dark:from-blue-900/20 dark:to-cyan-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-blue-600 to-cyan-600 rounded-lg flex items-center justify-center">
              <Newspaper className="w-5 h-5 text-white" />
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Press Monitor Settings</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Configure GDELT news monitoring</p>
            </div>
          </div>
        </div>

        <div className="p-5 space-y-4">
          {/* Enabled toggle */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Enable Press Monitor</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">Automatically check for news articles</p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={enabled}
                onChange={(e) => setEnabled(e.target.checked)}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-blue-600"></div>
            </label>
          </div>

          {/* Check interval */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Check Interval (hours)</label>
              <input
                type="number"
                min={1}
                max={168}
                value={checkIntervalHours}
                onChange={(e) => setCheckIntervalHours(parseInt(e.target.value) || 6)}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-blue-500"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">How often to check for new articles</p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Max Results Per Query</label>
              <input
                type="number"
                min={5}
                max={250}
                value={maxRecords}
                onChange={(e) => setMaxRecords(parseInt(e.target.value) || 25)}
                className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-blue-500"
              />
              <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">Maximum articles to fetch per celebrity</p>
            </div>
          </div>

          {/* Notifications toggle */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Push Notifications</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">Send notifications when new articles are found</p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={notifyNewArticles}
                onChange={(e) => setNotifyNewArticles(e.target.checked)}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-blue-600"></div>
            </label>
          </div>

          {/* Save button */}
          <div className="flex justify-end">
            <button
              onClick={saveSettings}
              disabled={saving}
              className="flex items-center space-x-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white rounded-lg transition-colors text-sm font-medium"
            >
              <Save className="w-4 h-4" />
              <span>{saving ? 'Saving...' : 'Save Settings'}</span>
            </button>
          </div>
        </div>
      </div>

      {/* Celebrity Selection Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-purple-50 to-pink-50 dark:from-purple-900/20 dark:to-pink-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-purple-600 to-pink-600 rounded-lg flex items-center justify-center">
              <Users className="w-5 h-5 text-white" />
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Celebrity Selection</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">
                {celebrityIds.length} of {celebList.length} celebrities selected for press monitoring
              </p>
            </div>
          </div>
        </div>

        <div className="p-5">
          {celebList.length > 0 ? (
            <div className="space-y-2">
              {celebList.map((celeb) => {
                const isEnabled = celebrityIds.includes(celeb.id)
                return (
                  <div
                    key={celeb.id}
                    className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg"
                  >
                    <div className="flex-1">
                      <p className="text-sm font-medium text-slate-900 dark:text-slate-100">{celeb.name}</p>
                    </div>
                    <label className="relative inline-flex items-center cursor-pointer ml-4">
                      <input
                        type="checkbox"
                        checked={isEnabled}
                        onChange={(e) => toggleCelebrity(celeb.id, e.target.checked)}
                        className="sr-only peer"
                      />
                      <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-purple-300 dark:peer-focus:ring-purple-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-purple-600"></div>
                    </label>
                  </div>
                )
              })}
            </div>
          ) : (
            <div className="text-center py-8 text-slate-500 dark:text-slate-400">
              <Users className="w-12 h-12 mx-auto mb-2 opacity-50" />
              <p>No tracked celebrities</p>
              <p className="text-xs mt-1">Add celebrities in the Celebrity Discovery page first</p>
            </div>
          )}
        </div>
      </div>
    </div>
  )
}

// About Tab
//
// ⚠️ IMPORTANT: VERSION AND FEATURES MUST BE UPDATED WITH EACH RELEASE ⚠️
//
function AppearancesTab() {
  const queryClient = useQueryClient()
  const [tmdbApiKey, setTmdbApiKey] = useState('')
  const [tmdbEnabled, setTmdbEnabled] = useState(true)
  const [checkInterval, setCheckInterval] = useState(12)
  const [notifyEnabled, setNotifyEnabled] = useState(true)
  const [notifyDaysBefore, setNotifyDaysBefore] = useState(1)
  const [notifyIncludePoster, setNotifyIncludePoster] = useState(true)
  const [notifyPlexMatches, setNotifyPlexMatches] = useState(true)
  const [podcastEnabled, setPodcastEnabled] = useState(false)
  const [radioEnabled, setRadioEnabled] = useState(false)
  const [podchaserApiKey, setPodchaserApiKey] = useState('')
  const [podchaserClientId, setPodchaserClientId] = useState('')
  const [podchaserClientSecret, setPodchaserClientSecret] = useState('')
  const [podchaserEnabled, setPodchaserEnabled] = useState(false)
  // Taddy configuration
  const [taddyUserId, setTaddyUserId] = useState('')
  const [taddyApiKey, setTaddyApiKey] = useState('')
  const [taddyUserId2, setTaddyUserId2] = useState('')
  const [taddyApiKey2, setTaddyApiKey2] = useState('')
  const [taddyEnabled, setTaddyEnabled] = useState(false)
  const [taddyLookbackDays, setTaddyLookbackDays] = useState(730)
  const [taddyMaxResults, setTaddyMaxResults] = useState(250)
  const [syncPastMovies, setSyncPastMovies] = useState(true)
  const [syncing, setSyncing] = useState(false)
  // Plex configuration
  const [plexUrl, setPlexUrl] = useState('')
  const [plexToken, setPlexToken] = useState('')
  const [plexConnected, setPlexConnected] = useState(false)
  const [plexServerName, setPlexServerName] = useState('')
  const [matchingPlex, setMatchingPlex] = useState(false)
  // Plex OAuth state
  const [plexAuthPending, setPlexAuthPending] = useState(false)
  const [plexPinId, setPlexPinId] = useState<number | null>(null)
  const [plexAuthUrl, setPlexAuthUrl] = useState('')
  const [plexServers, setPlexServers] = useState<Array<{
    name: string
    machineIdentifier: string
    owned: boolean
    url: string
    local: boolean
    relay?: boolean
    accessToken: string
    all_connections?: Array<{ url: string; local: boolean; relay: boolean }>
  }>>([])
  const [plexUser, setPlexUser] = useState<{ username: string; email: string } | null>(null)
  const [selectingServer, setSelectingServer] = useState(false)
  const [savingPlexServer, setSavingPlexServer] = useState(false)

  // Fetch appearance config (using new /appearances/config endpoint)
  const { data: appearanceConfig } = useQuery({
    queryKey: ['appearance-config'],
    queryFn: async () => {
      // First try the new appearances endpoint
      try {
        const newConfig = await api.getAppearanceConfig()
        // Also get the old config for API keys and other legacy fields
        const oldConfig = await api.get<{
          tmdb_api_key: string | null
          podchaser_api_key: string | null
          podchaser_client_id: string | null
          podchaser_client_secret: string | null
          tmdb_last_check: string | null
          podchaser_last_check: string | null
        }>('/config/appearance')

        // Merge both configs
        return {
          ...oldConfig,
          ...newConfig
        }
      } catch (error) {
        // Fallback to old endpoint if new one fails
        const response = await api.get<{
          tmdb_api_key: string | null
          tmdb_enabled: boolean
          tmdb_check_interval_hours: number
          tmdb_last_check: string | null
          notify_new_appearances: boolean
          notify_days_before: number
          podcast_enabled: boolean
          radio_enabled: boolean
          podchaser_api_key: string | null
          podchaser_client_id: string | null
          podchaser_client_secret: string | null
          podchaser_enabled: boolean
          podchaser_last_check: string | null
          sync_past_movies?: boolean
        }>('/config/appearance')
        return response
      }
    },
  })

  // Fetch tracked celebrities
  const { data: celebrities, refetch: refetchCelebrities } = useQuery({
    queryKey: ['tracked-celebrities'],
    queryFn: async () => {
      const response = await api.get<Array<{
        id: number
        name: string
        tmdb_person_id: number | null
        enabled: boolean
        tmdb_last_sync: string | null
      }>>('/celebrity/profiles?tracked_only=true')
      return response
    },
  })

  // Update state when config loads
  useEffect(() => {
    if (appearanceConfig) {
      setTmdbApiKey(appearanceConfig.tmdb_api_key || '')
      setTmdbEnabled(appearanceConfig.tmdb_enabled ?? true)
      setCheckInterval(appearanceConfig.tmdb_check_interval_hours ?? 12)
      setNotifyEnabled(appearanceConfig.notify_new_appearances ?? true)
      setNotifyDaysBefore(appearanceConfig.notify_days_before ?? 1)
      setNotifyIncludePoster((appearanceConfig as any).notify_include_poster ?? true)
      setNotifyPlexMatches((appearanceConfig as any).notify_plex_matches ?? true)
      setPodcastEnabled((appearanceConfig as any).podcast_enabled ?? false)
      setRadioEnabled((appearanceConfig as any).radio_enabled ?? false)
      setPodchaserApiKey(appearanceConfig.podchaser_api_key || '')
      setPodchaserClientId(appearanceConfig.podchaser_client_id || '')
      setPodchaserClientSecret(appearanceConfig.podchaser_client_secret || '')
      setPodchaserEnabled((appearanceConfig as any).podchaser_enabled ?? false)
      // Taddy config
      setTaddyUserId((appearanceConfig as any).taddy_user_id || '')
      setTaddyApiKey((appearanceConfig as any).taddy_api_key || '')
      setTaddyUserId2((appearanceConfig as any).taddy_user_id_2 || '')
      setTaddyApiKey2((appearanceConfig as any).taddy_api_key_2 || '')
      setTaddyEnabled((appearanceConfig as any).taddy_enabled ?? false)
      setTaddyLookbackDays((appearanceConfig as any).taddy_lookback_days ?? 730)
      setTaddyMaxResults((appearanceConfig as any).taddy_max_results ?? 250)
      setSyncPastMovies(appearanceConfig.sync_past_movies ?? true)
      // Plex config
      if ((appearanceConfig as any).plex_url) setPlexUrl((appearanceConfig as any).plex_url)
      if ((appearanceConfig as any).plex_token) setPlexToken((appearanceConfig as any).plex_token)
    }
  }, [appearanceConfig])

  // Check Plex connection status on load if credentials exist
  useEffect(() => {
    if (plexUrl && plexToken) {
      // If we have credentials, consider connected (OAuth already validated them)
      setPlexConnected(true)
      // Try to get server name from the URL or test connection
      api.testPlexConnection().then((result) => {
        if (result.success && result.server_name) {
          setPlexServerName(result.server_name)
        } else {
          // Connection test failed but credentials are saved - still "connected"
          setPlexServerName('Plex Server')
        }
      }).catch(() => {
        // Keep connected status since we have credentials
        setPlexServerName('Plex Server')
      })
    }
  }, [plexUrl, plexToken])

  // Plex OAuth polling - check if user has authenticated
  useEffect(() => {
    if (!plexPinId || !plexAuthPending) return

    const pollInterval = setInterval(async () => {
      try {
        const result = await api.checkPlexAuth(plexPinId)
        if (result.authenticated && result.servers) {
          setPlexAuthPending(false)
          setPlexServers(result.servers)
          setPlexUser(result.user || null)
          setSelectingServer(true)
          clearInterval(pollInterval)
        }
      } catch (error) {
        console.error('Error checking Plex auth:', error)
      }
    }, 2000) // Poll every 2 seconds

    // Cleanup on unmount or when auth completes
    return () => clearInterval(pollInterval)
  }, [plexPinId, plexAuthPending])

  // Save config mutation
  const saveConfigMutation = useMutation({
    mutationFn: async () => {
      // Save to old endpoint for API keys
      await api.post('/config/appearance', {
        tmdb_api_key: tmdbApiKey,
        tmdb_enabled: tmdbEnabled,
        tmdb_check_interval_hours: checkInterval,
        notify_new_appearances: notifyEnabled,
        notify_days_before: notifyDaysBefore,
        podcast_enabled: podcastEnabled,
        radio_enabled: radioEnabled,
        podchaser_api_key: podchaserApiKey,
        podchaser_client_id: podchaserClientId,
        podchaser_client_secret: podchaserClientSecret,
        podchaser_enabled: podchaserEnabled,
      })

      // Also save to new endpoint for new settings
      await api.updateAppearanceConfig({
        tmdb_enabled: tmdbEnabled,
        tmdb_check_interval_hours: checkInterval,
        notify_new_appearances: notifyEnabled,
        notify_days_before: notifyDaysBefore,
        notify_include_poster: notifyIncludePoster,
        notify_plex_matches: notifyPlexMatches,
        sync_past_movies: syncPastMovies,
        // Taddy settings
        taddy_user_id: taddyUserId,
        taddy_api_key: taddyApiKey,
        taddy_user_id_2: taddyUserId2,
        taddy_api_key_2: taddyApiKey2,
        taddy_enabled: taddyEnabled,
        taddy_lookback_days: taddyLookbackDays,
        taddy_max_results: taddyMaxResults,
      })

      // Save Plex URL if changed
      if (plexUrl && plexToken) {
        await api.configurePlex({ plex_url: plexUrl, plex_token: plexToken })
      }
    },
    onSuccess: () => {
      notificationManager.settingsSaved('Appearance tracking')
      queryClient.invalidateQueries({ queryKey: ['appearance-config'] })
    },
    onError: (err: unknown) => {
      notificationManager.settingsSaveError(err, 'Appearance tracking')
    },
  })

  // Toggle celebrity enabled status
  const toggleCelebrityMutation = useMutation({
    mutationFn: async ({ id, enabled }: { id: number; enabled: boolean }) => {
      return api.post(`/celebrity/profiles/${id}/toggle`, { enabled })
    },
    onSuccess: () => {
      notificationManager.success('Updated', 'Celebrity tracking status updated')
      refetchCelebrities()
    },
    onError: (err: unknown) => {
      notificationManager.apiError('Update Failed', err, 'Failed to update celebrity')
    },
  })

  // Sync now mutation
  const syncNowMutation = useMutation({
    mutationFn: async () => {
      setSyncing(true)
      return api.syncAppearances()
    },
    onSuccess: () => {
      notificationManager.syncStarted('Appearance')
      setSyncing(false)
    },
    onError: (err: unknown) => {
      notificationManager.syncError('Appearance', err)
      setSyncing(false)
    },
  })

  // Plex matching stats
  const { data: plexStats, refetch: refetchPlexStats } = useQuery({
    queryKey: ['plex-stats'],
    queryFn: () => api.getPlexStats(),
    enabled: plexConnected,
    refetchInterval: matchingPlex ? 3000 : 30000, // Fast poll while matching, slow poll otherwise
  })

  // Match appearances to Plex
  const matchPlexMutation = useMutation({
    mutationFn: async () => {
      setMatchingPlex(true)
      return api.matchAppearancesToPlex()
    },
    onSuccess: () => {
      // Matching runs in background - poll for completion
      // Check periodically if matching is done by comparing stats
      let checkCount = 0
      const checkInterval = setInterval(async () => {
        checkCount++
        await refetchPlexStats()
        // Stop after 2 minutes max or 40 checks
        if (checkCount >= 40) {
          clearInterval(checkInterval)
          setMatchingPlex(false)
          queryClient.invalidateQueries({ queryKey: ['all-appearances'] })
        }
      }, 3000)
      // Also stop after timeout as fallback
      setTimeout(() => {
        clearInterval(checkInterval)
        setMatchingPlex(false)
        refetchPlexStats()
        queryClient.invalidateQueries({ queryKey: ['all-appearances'] })
      }, 120000) // Stop after 2 minutes max
    },
    onError: (err: unknown) => {
      setMatchingPlex(false)
      notificationManager.apiError('Matching Failed', err, 'Could not match to Plex')
    },
  })

  // Start Plex OAuth flow
  const startPlexAuth = async () => {
    try {
      setPlexAuthPending(true)
      const result = await api.startPlexAuth()
      if (result.success) {
        setPlexPinId(result.pin_id)
        setPlexAuthUrl(result.auth_url)
        // Open Plex auth in new tab
        window.open(result.auth_url, '_blank')
      } else {
        setPlexAuthPending(false)
        notificationManager.connectionFailed('Plex', 'Could not start authentication')
      }
    } catch (err: unknown) {
      setPlexAuthPending(false)
      notificationManager.connectionFailed('Plex', err)
    }
  }

  // Cancel Plex OAuth
  const cancelPlexAuth = () => {
    setPlexAuthPending(false)
    setPlexPinId(null)
    setPlexAuthUrl('')
    setPlexServers([])
    setPlexUser(null)
    setSelectingServer(false)
  }

  // Save selected Plex server
  const saveSelectedPlexServer = async (server: typeof plexServers[0]) => {
    try {
      setSavingPlexServer(true)
      const result = await api.savePlexAuth({
        server_url: server.url,
        server_token: server.accessToken,
        server_name: server.name,
        machine_identifier: server.machineIdentifier,
      })
      if (result.success) {
        setPlexUrl(server.url)
        setPlexToken(server.accessToken)
        setPlexConnected(true)
        setPlexServerName(server.name)
        setSelectingServer(false)
        setPlexServers([])
        setPlexUser(null)
        notificationManager.connectionSuccess('Plex', `Connected to ${server.name}`)
      } else {
        notificationManager.connectionFailed('Plex', result.message)
      }
    } catch (err: unknown) {
      notificationManager.connectionFailed('Plex', err)
    } finally {
      setSavingPlexServer(false)
    }
  }

  // Disconnect from Plex
  const disconnectPlex = async () => {
    try {
      await api.configurePlex({ plex_url: '', plex_token: '' })
      setPlexUrl('')
      setPlexToken('')
      setPlexConnected(false)
      setPlexServerName('')
      notificationManager.disconnected('Plex')
    } catch (err: unknown) {
      notificationManager.apiError('Error', err, 'Could not disconnect Plex')
    }
  }

  return (
    <div className="space-y-6">
      {/* Tracked Celebrities Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-purple-50 to-pink-50 dark:from-purple-900/20 dark:to-pink-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center justify-between">
            <div className="flex items-center space-x-3">
              <div className="w-10 h-10 bg-gradient-to-br from-purple-600 to-pink-600 rounded-lg flex items-center justify-center">
                <UserPlus className="w-5 h-5 text-white" />
              </div>
              <div>
                <h3 className="font-semibold text-slate-900 dark:text-slate-100">Tracked Celebrities</h3>
                <p className="text-xs text-slate-500 dark:text-slate-400">
                  {celebrities?.length || 0} tracked for appearances
                </p>
              </div>
            </div>
          </div>
        </div>

        <div className="p-5">
          {celebrities && celebrities.length > 0 ? (
            <div className="space-y-2">
              {celebrities.map((celeb) => (
                <div
                  key={celeb.id}
                  className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg"
                >
                  <div className="flex-1">
                    <p className="text-sm font-medium text-slate-900 dark:text-slate-100">{celeb.name}</p>
                    <div className="flex items-center gap-2 mt-1">
                      {celeb.tmdb_person_id ? (
                        <span className="text-xs px-2 py-0.5 bg-green-500/10 text-green-600 dark:text-green-400 rounded">
                          TMDb ID: {celeb.tmdb_person_id}
                        </span>
                      ) : (
                        <span className="text-xs px-2 py-0.5 bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 rounded">
                          No TMDb ID
                        </span>
                      )}
                      {celeb.tmdb_last_sync && (
                        <span className="text-xs text-slate-500 dark:text-slate-400">
                          Last sync: {new Date(celeb.tmdb_last_sync).toLocaleDateString()}
                        </span>
                      )}
                    </div>
                  </div>
                  <label className="relative inline-flex items-center cursor-pointer ml-4">
                    <input
                      type="checkbox"
                      checked={celeb.enabled}
                      onChange={(e) => toggleCelebrityMutation.mutate({ id: celeb.id, enabled: e.target.checked })}
                      className="sr-only peer"
                    />
                    <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-purple-300 dark:peer-focus:ring-purple-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-purple-600"></div>
                  </label>
                </div>
              ))}
            </div>
          ) : (
            <div className="text-center py-8 text-slate-500 dark:text-slate-400">
              <UserPlus className="w-12 h-12 mx-auto mb-2 opacity-50" />
              <p>No tracked celebrities</p>
              <p className="text-xs mt-1">Add celebrities in Celebrity Discovery page</p>
            </div>
          )}
        </div>
      </div>

      {/* Notifications Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-amber-50 to-orange-50 dark:from-amber-900/20 dark:to-orange-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-amber-600 to-orange-600 rounded-lg flex items-center justify-center">
              <Settings className="w-5 h-5 text-white" />
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Notifications</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Get notified about upcoming appearances</p>
            </div>
          </div>
        </div>

        <div className="p-5 space-y-4">
          {/* Enable Notifications */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Enable Notifications</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">
                Notify when new appearances are discovered
              </p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={notifyEnabled}
                onChange={(e) => setNotifyEnabled(e.target.checked)}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-amber-300 dark:peer-focus:ring-amber-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-amber-600"></div>
            </label>
          </div>

          {/* Notification Days Before */}
          <div>
            <label className="block text-sm font-medium text-slate-900 dark:text-slate-100 mb-2">
              Notify Days Before
            </label>
            <input
              type="number"
              min="0"
              max="30"
              value={notifyDaysBefore}
              onChange={(e) => setNotifyDaysBefore(parseInt(e.target.value) || 1)}
              disabled={!notifyEnabled}
              className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-amber-500 disabled:opacity-50 disabled:cursor-not-allowed"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              How many days before an appearance to send notification (0-30 days)
            </p>
          </div>

          {/* Include Poster in Notifications */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Include Poster Images</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">
                Attach poster/artwork to push notifications
              </p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={notifyIncludePoster}
                onChange={(e) => setNotifyIncludePoster(e.target.checked)}
                disabled={!notifyEnabled}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-amber-300 dark:peer-focus:ring-amber-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-amber-600 peer-disabled:opacity-50"></div>
            </label>
          </div>

          {/* Notify on Plex Matches */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Notify on Plex Matches</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">
                Send push notification when new Plex library matches are found
              </p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={notifyPlexMatches}
                onChange={(e) => setNotifyPlexMatches(e.target.checked)}
                disabled={!notifyEnabled}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-amber-300 dark:peer-focus:ring-amber-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-amber-600 peer-disabled:opacity-50"></div>
            </label>
          </div>
        </div>
      </div>

      {/* TMDb Configuration Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-cyan-50 to-blue-50 dark:from-cyan-900/20 dark:to-blue-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-cyan-600 to-blue-600 rounded-lg flex items-center justify-center">
              <Calendar className="w-5 h-5 text-white" />
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">TMDb TV Tracking</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">The Movie Database API integration</p>
            </div>
          </div>
        </div>

        <div className="p-5 space-y-4">
          {/* TMDb API Key */}
          <div>
            <label className="block text-sm font-medium text-slate-900 dark:text-slate-100 mb-2">
              TMDb API Key
            </label>
            <input
              type="password"
              value={tmdbApiKey}
              onChange={(e) => setTmdbApiKey(e.target.value)}
              placeholder="Enter TMDb API key"
              className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-blue-500"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              Get your free API key from{' '}
              <a
                href="https://www.themoviedb.org/settings/api"
                target="_blank"
                rel="noopener noreferrer"
                className="text-blue-600 dark:text-blue-400 hover:underline"
              >
                TMDb
              </a>
            </p>
          </div>

          {/* Check Interval */}
          <div>
            <label className="block text-sm font-medium text-slate-900 dark:text-slate-100 mb-2">
              Check Interval (hours)
            </label>
            <input
              type="number"
              min="1"
              max="168"
              value={checkInterval}
              onChange={(e) => setCheckInterval(parseInt(e.target.value) || 12)}
              className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-blue-500"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              How often to check for new appearances (1-168 hours)
            </p>
          </div>

          {/* Enable TMDb Sync */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Enable TMDb Sync</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">
                Automatically discover TV show appearances
              </p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={tmdbEnabled}
                onChange={(e) => setTmdbEnabled(e.target.checked)}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-blue-600"></div>
            </label>
          </div>

          {/* Sync Past Movies */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Sync Past Movies</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">
                Include complete movie filmography in sync (not just upcoming)
              </p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={syncPastMovies}
                onChange={(e) => setSyncPastMovies(e.target.checked)}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-blue-600"></div>
            </label>
          </div>

          {/* Last Check Info */}
          {appearanceConfig?.tmdb_last_check && (
            <div className="p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
              <p className="text-xs text-slate-600 dark:text-slate-400">
                Last checked:{' '}
                <span className="font-medium text-slate-900 dark:text-slate-100">
                  {new Date(appearanceConfig.tmdb_last_check).toLocaleString()}
                </span>
              </p>
            </div>
          )}
        </div>
      </div>

      {/* Podchaser Configuration Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-green-600 to-emerald-600 rounded-lg flex items-center justify-center">
              <Mic className="w-5 h-5 text-white" />
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Podchaser Podcast Tracking</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Track podcast guest appearances</p>
            </div>
          </div>
        </div>

        <div className="p-5 space-y-4">
          {/* Podchaser Client ID */}
          <div>
            <label className="block text-sm font-medium text-slate-900 dark:text-slate-100 mb-2">
              Podchaser Client ID
            </label>
            <input
              type="text"
              value={podchaserClientId}
              onChange={(e) => setPodchaserClientId(e.target.value)}
              placeholder="Enter Podchaser Client ID"
              className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-green-500"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              Get your free API credentials from{' '}
              <a
                href="https://www.podchaser.com/api"
                target="_blank"
                rel="noopener noreferrer"
                className="text-green-600 dark:text-green-400 hover:underline"
              >
                Podchaser
              </a>
            </p>
          </div>

          {/* Podchaser Client Secret */}
          <div>
            <label className="block text-sm font-medium text-slate-900 dark:text-slate-100 mb-2">
              Podchaser Client Secret
            </label>
            <input
              type="password"
              value={podchaserClientSecret}
              onChange={(e) => setPodchaserClientSecret(e.target.value)}
              placeholder="Enter Podchaser Client Secret"
              className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-green-500"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              These credentials are used to generate access tokens for API authentication
            </p>
          </div>

          {/* Podchaser API Key (Access Token) */}
          <div>
            <label className="block text-sm font-medium text-slate-900 dark:text-slate-100 mb-2">
              Podchaser Access Token
            </label>
            <input
              type="text"
              value={podchaserApiKey}
              onChange={(e) => setPodchaserApiKey(e.target.value)}
              placeholder="Auto-generated from client credentials"
              className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-slate-100 dark:bg-slate-900 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-green-500 font-mono text-xs"
              readOnly
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              This token is automatically generated when you sync with the credentials above
            </p>
          </div>

          {/* Enable Podchaser Sync */}
          <div className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Enable Podchaser Sync</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">
                Automatically discover podcast guest appearances
              </p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={podchaserEnabled}
                onChange={(e) => setPodchaserEnabled(e.target.checked)}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-green-300 dark:peer-focus:ring-green-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-green-600"></div>
            </label>
          </div>

          {/* Last Check Info */}
          {appearanceConfig?.podchaser_last_check && (
            <div className="p-3 bg-green-50 dark:bg-green-900/20 rounded-lg">
              <p className="text-xs text-slate-600 dark:text-slate-400">
                Last checked:{' '}
                <span className="font-medium text-slate-900 dark:text-slate-100">
                  {new Date(appearanceConfig.podchaser_last_check).toLocaleString()}
                </span>
              </p>
            </div>
          )}
        </div>
      </div>

      {/* Taddy Podcast Configuration Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-orange-50 to-red-50 dark:from-orange-900/20 dark:to-red-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center space-x-3">
            <div className="w-10 h-10 bg-gradient-to-br from-orange-600 to-red-600 rounded-lg flex items-center justify-center">
              <Mic className="w-5 h-5 text-white" />
            </div>
            <div>
              <h3 className="font-semibold text-slate-900 dark:text-slate-100">Taddy Podcast Tracking</h3>
              <p className="text-xs text-slate-500 dark:text-slate-400">Search for podcast appearances via Taddy API</p>
            </div>
          </div>
        </div>

        <div className="p-5 space-y-4">
          {/* Taddy User ID */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Taddy User ID
            </label>
            <input
              type="text"
              value={taddyUserId}
              onChange={(e) => setTaddyUserId(e.target.value)}
              placeholder="Enter Taddy User ID"
              className="w-full px-3 py-2 bg-white/50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg text-sm"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              Get your credentials from{' '}
              <a
                href="https://taddy.org/developers/podcast-api"
                target="_blank"
                rel="noopener noreferrer"
                className="text-orange-600 hover:underline"
              >
                Taddy Developer Portal
              </a>
            </p>
          </div>

          {/* Taddy API Key */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Taddy API Key
            </label>
            <input
              type="password"
              value={taddyApiKey}
              onChange={(e) => setTaddyApiKey(e.target.value)}
              placeholder="Enter Taddy API Key"
              className="w-full px-3 py-2 bg-white/50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg text-sm"
            />
          </div>

          {/* Fallback Account Section */}
          <div className="col-span-2 border-t border-slate-200 dark:border-slate-700 pt-4 mt-2">
            <p className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">
              Fallback Account (Optional)
            </p>
            <p className="text-xs text-slate-500 dark:text-slate-400 mb-3">
              Configure a second Taddy account to use when the primary account's quota is exceeded.
            </p>
            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Fallback User ID
                </label>
                <input
                  type="text"
                  value={taddyUserId2}
                  onChange={(e) => setTaddyUserId2(e.target.value)}
                  placeholder="Enter fallback User ID"
                  className="w-full px-3 py-2 bg-white/50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg text-sm"
                />
              </div>
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Fallback API Key
                </label>
                <input
                  type="password"
                  value={taddyApiKey2}
                  onChange={(e) => setTaddyApiKey2(e.target.value)}
                  placeholder="Enter fallback API Key"
                  className="w-full px-3 py-2 bg-white/50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg text-sm"
                />
              </div>
            </div>
          </div>

          {/* Lookback Days */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Lookback Period (days)
            </label>
            <input
              type="number"
              value={taddyLookbackDays}
              onChange={(e) => setTaddyLookbackDays(parseInt(e.target.value) || 730)}
              min={30}
              max={1825}
              className="w-full px-3 py-2 bg-white/50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg text-sm"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              How far back to search for podcast appearances (default: 730 days / 2 years)
            </p>
          </div>

          {/* Max Results */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
              Max Results
            </label>
            <input
              type="number"
              value={taddyMaxResults}
              onChange={(e) => setTaddyMaxResults(parseInt(e.target.value) || 250)}
              min={25}
              max={500}
              step={25}
              className="w-full px-3 py-2 bg-white/50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg text-sm"
            />
            <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
              Maximum podcast results to fetch per celebrity (default: 250, max: 500)
            </p>
          </div>

          {/* Enable Taddy Sync */}
          <div className="flex items-center justify-between">
            <div>
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100">Enable Taddy Sync</p>
              <p className="text-xs text-slate-500 dark:text-slate-400">Search for podcast appearances during sync</p>
            </div>
            <label className="relative inline-flex items-center cursor-pointer">
              <input
                type="checkbox"
                checked={taddyEnabled}
                onChange={(e) => setTaddyEnabled(e.target.checked)}
                className="sr-only peer"
              />
              <div className="w-11 h-6 bg-slate-300 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-slate-600 peer-checked:bg-orange-600"></div>
            </label>
          </div>

          {/* Last Check Info */}
          {(appearanceConfig as any)?.taddy_last_check && (
            <div className="p-3 bg-orange-50 dark:bg-orange-900/20 rounded-lg">
              <p className="text-xs text-slate-600 dark:text-slate-400">
                Last checked:{' '}
                <span className="font-medium text-slate-900 dark:text-slate-100">
                  {new Date((appearanceConfig as any).taddy_last_check).toLocaleString()}
                </span>
              </p>
            </div>
          )}
        </div>
      </div>

      {/* Plex Integration Card */}
      <div className="card-glass-hover rounded-xl overflow-hidden border border-white/10">
        <div className="bg-gradient-to-r from-yellow-50 to-amber-50 dark:from-yellow-900/20 dark:to-amber-900/20 border-b border-slate-200 dark:border-slate-700 px-5 py-4">
          <div className="flex items-center justify-between">
            <div className="flex items-center space-x-3">
              <div className="w-10 h-10 bg-gradient-to-br from-yellow-600 to-amber-600 rounded-lg flex items-center justify-center">
                <Play className="w-5 h-5 text-white" />
              </div>
              <div>
                <h3 className="font-semibold text-slate-900 dark:text-slate-100">Plex Integration</h3>
                <p className="text-xs text-slate-500 dark:text-slate-400">Link appearances to your Plex library</p>
              </div>
            </div>
            {plexConnected && (
              <span className="text-xs px-2 py-1 bg-green-500/10 text-green-600 dark:text-green-400 rounded-lg flex items-center gap-1">
                <CheckCircle className="w-3 h-3" />
                Connected
              </span>
            )}
          </div>
        </div>

        <div className="p-5 space-y-4">
          {/* Not connected - Show Sign in button */}
          {!plexConnected && !plexAuthPending && !selectingServer && (
            <div className="text-center py-4">
              <p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
                Sign in to your Plex account to link appearances with your library
              </p>
              <button
                onClick={startPlexAuth}
                className="bg-[#E5A00D] hover:bg-[#CC8E0C] text-black px-6 py-3 rounded-lg font-medium transition-colors flex items-center justify-center gap-2 mx-auto"
              >
                <Play className="w-5 h-5" />
                Sign in with Plex
              </button>
            </div>
          )}

          {/* Auth pending - Waiting for user to authenticate */}
          {plexAuthPending && !selectingServer && (
            <div className="text-center py-4">
              <Loader2 className="w-8 h-8 animate-spin text-yellow-600 mx-auto mb-3" />
              <p className="text-sm text-slate-900 dark:text-slate-100 font-medium mb-2">
                Waiting for Plex authentication...
              </p>
              <p className="text-xs text-slate-500 dark:text-slate-400 mb-4">
                Complete the sign-in in the new tab that opened
              </p>
              <div className="flex gap-3 justify-center">
                <a
                  href={plexAuthUrl}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-sm text-yellow-600 dark:text-yellow-400 hover:underline"
                >
                  Open Plex login again
                </a>
                <button
                  onClick={cancelPlexAuth}
                  className="text-sm text-slate-500 hover:text-slate-700 dark:hover:text-slate-300"
                >
                  Cancel
                </button>
              </div>
            </div>
          )}

          {/* Server selection - User authenticated, choose server */}
          {selectingServer && plexServers.length > 0 && (
            <div>
              {plexUser && (
                <p className="text-sm text-slate-600 dark:text-slate-400 mb-3">
                  Signed in as <span className="font-medium text-slate-900 dark:text-slate-100">{plexUser.username}</span>
                </p>
              )}
              <p className="text-sm font-medium text-slate-900 dark:text-slate-100 mb-3">
                Select a Plex server and connection:
              </p>
              <div className="space-y-4">
                {plexServers.map((server) => (
                  <div key={server.machineIdentifier} className="p-3 rounded-lg border border-slate-200 dark:border-slate-700">
                    <div className="flex items-center gap-3 mb-3">
                      <div className="w-8 h-8 bg-yellow-100 dark:bg-yellow-900/30 rounded-lg flex items-center justify-center">
                        <Play className="w-4 h-4 text-yellow-600" />
                      </div>
                      <div>
                        <p className="font-medium text-slate-900 dark:text-slate-100">{server.name}</p>
                        <p className="text-xs text-slate-500 dark:text-slate-400">
                          {server.owned ? 'Owned' : 'Shared'}
                        </p>
                      </div>
                    </div>
                    {/* Connection options dropdown */}
                    <div className="space-y-2">
                      <label className="block text-xs text-slate-500 dark:text-slate-400">
                        Choose connection ({(server as any).all_connections?.length || 1} available):
                      </label>
                      <select
                        className="w-full px-3 py-2 text-sm rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100"
                        defaultValue={server.url}
                        onChange={(e) => {
                          const selectedUrl = e.target.value
                          const conn = (server as any).all_connections?.find((c: any) => c.url === selectedUrl)
                          // Update server object with selected URL
                          server.url = selectedUrl
                          server.local = conn?.local || false
                        }}
                      >
                        {(server as any).all_connections?.map((conn: any, idx: number) => (
                          <option key={idx} value={conn.url}>
                            {conn.url} {conn.local ? '(Local)' : conn.relay ? '(Relay)' : '(Remote)'}
                          </option>
                        )) || (
                          <option value={server.url}>{server.url}</option>
                        )}
                      </select>
                      <button
                        onClick={() => saveSelectedPlexServer(server)}
                        disabled={savingPlexServer}
                        className="w-full py-2 bg-yellow-600 hover:bg-yellow-700 text-white rounded-lg font-medium transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
                      >
                        {savingPlexServer ? (
                          <>
                            <Loader2 className="w-4 h-4 animate-spin" />
                            Connecting...
                          </>
                        ) : (
                          <>
                            Use this server
                          </>
                        )}
                      </button>
                    </div>
                  </div>
                ))}
              </div>
              <button
                onClick={cancelPlexAuth}
                className="mt-3 text-sm text-slate-500 hover:text-slate-700 dark:hover:text-slate-300"
              >
                Cancel
              </button>
            </div>
          )}

          {/* Connected state */}
          {plexConnected && plexServerName && (
            <>
              <div className="p-4 bg-green-50 dark:bg-green-900/20 rounded-lg flex items-center justify-between">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 bg-green-100 dark:bg-green-900/30 rounded-lg flex items-center justify-center">
                    <CheckCircle className="w-5 h-5 text-green-600" />
                  </div>
                  <div>
                    <p className="font-medium text-slate-900 dark:text-slate-100">{plexServerName}</p>
                    <p className="text-xs text-slate-500 dark:text-slate-400">Connected</p>
                  </div>
                </div>
                <button
                  onClick={disconnectPlex}
                  className="text-sm text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
                >
                  Disconnect
                </button>
              </div>

              {/* Manual URL Override */}
              <div className="p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
                <label className="block text-xs font-medium text-slate-700 dark:text-slate-300 mb-1">
                  Server URL (change if auto-detected URL is not accessible)
                </label>
                <div className="flex gap-2">
                  <input
                    type="text"
                    value={plexUrl}
                    onChange={(e) => setPlexUrl(e.target.value)}
                    placeholder="https://your-plex-server:32400"
                    className="flex-1 px-3 py-1.5 text-sm rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100"
                  />
                  <button
                    onClick={async () => {
                      const result = await api.testPlexConnection()
                      if (result.success) {
                        notificationManager.connectionSuccess('Plex', `Connected to ${result.server_name}`)
                      } else {
                        notificationManager.connectionFailed('Plex', result.message)
                      }
                    }}
                    className="px-3 py-1.5 text-sm bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 rounded-lg transition-colors"
                  >
                    Test
                  </button>
                </div>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
                  Current: {plexUrl || 'Not set'}
                </p>
              </div>

              {/* Plex Match Stats */}
              {plexStats && (
                <div className="p-4 bg-slate-50 dark:bg-slate-800/50 rounded-lg">
                  <div className="flex items-center justify-between mb-3">
                    <span className="text-sm font-medium text-slate-900 dark:text-slate-100">Library Matching</span>
                    <span className="text-xs px-2 py-1 rounded-full bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400">
                      {plexStats.percentage}% matched
                    </span>
                  </div>
                  <div className="w-full bg-slate-200 dark:bg-slate-700 rounded-full h-1.5 sm:h-2 mb-3">
                    <div
                      className="bg-green-500 h-1.5 sm:h-2 rounded-full transition-all duration-500"
                      style={{ width: `${plexStats.percentage}%` }}
                    />
                  </div>
                  <div className="grid grid-cols-3 gap-2 text-center text-xs">
                    <div>
                      <p className="font-medium text-slate-900 dark:text-slate-100">{plexStats.matched}</p>
                      <p className="text-slate-500 dark:text-slate-400">Matched</p>
                    </div>
                    <div>
                      <p className="font-medium text-slate-900 dark:text-slate-100">{plexStats.unmatched}</p>
                      <p className="text-slate-500 dark:text-slate-400">Unmatched</p>
                    </div>
                    <div>
                      <p className="font-medium text-slate-900 dark:text-slate-100">{plexStats.total}</p>
                      <p className="text-slate-500 dark:text-slate-400">Total</p>
                    </div>
                  </div>
                  {plexStats.breakdown && (
                    <div className="mt-3 pt-3 border-t border-slate-200 dark:border-slate-700 text-xs text-slate-500 dark:text-slate-400">
                      {plexStats.breakdown.Movie && (
                        <span className="mr-3">Movies: {plexStats.breakdown.Movie.matched}/{plexStats.breakdown.Movie.total}</span>
                      )}
                      {plexStats.breakdown.TV && (
                        <span>TV: {plexStats.breakdown.TV.matched}/{plexStats.breakdown.TV.total}</span>
                      )}
                    </div>
                  )}
                </div>
              )}

              {/* Plex Actions */}
              <div className="flex gap-3">
                <button
                  onClick={() => matchPlexMutation.mutate()}
                  disabled={matchingPlex}
                  className="flex-1 bg-amber-600 hover:bg-amber-700 text-white px-4 py-2 rounded-lg font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2 text-sm"
                >
                  {matchingPlex ? (
                    <>
                      <Loader2 className="w-4 h-4 animate-spin" />
                      Matching...
                    </>
                  ) : (
                    <>
                      <LinkIcon className="w-4 h-4" />
                      Match to Library
                    </>
                  )}
                </button>
              </div>
            </>
          )}
        </div>
      </div>

      {/* Action Buttons */}
      <div className="flex gap-3">
        <button
          onClick={() => saveConfigMutation.mutate()}
          disabled={saveConfigMutation.isPending}
          className="flex-1 bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
        >
          {saveConfigMutation.isPending ? (
            <>
              <Loader2 className="w-4 h-4 animate-spin" />
              Saving...
            </>
          ) : (
            <>
              <Save className="w-4 h-4" />
              Save Settings
            </>
          )}
        </button>

            <button
              onClick={() => syncNowMutation.mutate()}
              disabled={syncing || (!tmdbApiKey && !podchaserApiKey)}
              className="flex-1 bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
            >
              {syncing ? (
                <>
                  <Loader2 className="w-4 h-4 animate-spin" />
                  Syncing...
                </>
              ) : (
                <>
                  <RefreshCw className="w-4 h-4" />
                  Sync Now
                </>
              )}
            </button>
      </div>

      {/* Info Card */}
      <div className="card-glass-hover rounded-xl p-4 border border-slate-200 dark:border-slate-700">
        <div className="flex items-start gap-3">
          <div className="w-8 h-8 bg-blue-100 dark:bg-blue-900/30 rounded-lg flex items-center justify-center flex-shrink-0">
            <Info className="w-4 h-4 text-blue-600 dark:text-blue-400" />
          </div>
          <div className="flex-1">
            <h4 className="text-sm font-medium text-slate-900 dark:text-slate-100 mb-1">
              How It Works
            </h4>
            <p className="text-xs text-slate-600 dark:text-slate-400 leading-relaxed">
              The appearance tracker uses TMDb (The Movie Database) API to discover upcoming TV show appearances
              for your tracked celebrities. The system automatically checks for new episodes and displays the next
              5 upcoming appearances on your dashboard. You can click any appearance to see full details and mark
              them as watched.
            </p>
          </div>
        </div>
      </div>
    </div>
  )
}

// When creating a new version:
// 1. Update the version number below (currently v13.13.1)
// ============================================================================
// CLOUD BACKUP TAB
// ============================================================================

interface CloudBackupConfig {
  enabled: boolean
  provider: string
  endpoint: string
  bucket: string
  key_id: string | null
  application_key: string | null
  encryption_enabled: boolean
  encryption_password: string | null
  encryption_salt: string | null
  include_dirs: string[]
  exclude_dirs: string[]
  cooldown_seconds: number
  bandwidth_limit: string | null
}

interface CloudBackupStatus {
  configured: boolean
  enabled: boolean
  service_status: string
  syncing: boolean
  last_sync: string | null
  last_sync_status: string | null
  files_watched: number
  storage_used: number | null
  error_count: number
  last_error: string | null
  cooldown_remaining: number
  active_job: {
    id: string
    status: string
    dirs_synced: number
    dirs_total: number
    current_dir: string | null
    current_file: string | null
    phase: string | null
    transfer_stats: {
      bytes_done?: string
      bytes_total?: string
      pct?: number
      speed?: string
      eta?: string
      files_done?: number
      files_total?: number
      checks_done?: number
      checks_total?: number
    } | null
  } | null
  state: string
}

interface CloudStorageDir {
  name: string
  files: number
  size: number
  size_human: string
  error?: string
}

interface CloudStorageStatus {
  provider: string
  bucket: string
  endpoint: string
  encryption: boolean
  total_files: number | null
  total_size: number | null
  total_size_human: string | null
  directories: CloudStorageDir[]
  error: string | null
  queried_at: string | null
  query_status: string
  query_running: boolean
}

function CloudBackupTab() {
  const queryClient = useQueryClient()
  const [showPasswords, setShowPasswords] = useState(false)
  const [formData, setFormData] = useState<Partial<CloudBackupConfig>>({})
  const [hasChanges, setHasChanges] = useState(false)

  // Fetch config
  const { data: config, isLoading: configLoading } = useQuery<CloudBackupConfig>({
    queryKey: ['cloud-backup-config'],
    queryFn: () => api.get('/cloud-backup/config'),
  })

  // Fetch status (auto-refresh every 10s)
  const { data: status } = useQuery<CloudBackupStatus>({
    queryKey: ['cloud-backup-status'],
    queryFn: () => api.get('/cloud-backup/status'),
    refetchInterval: (query) => query.state.data?.syncing ? 3000 : 10000,
  })

  // Fetch logs (faster during sync)
  const { data: logsData, refetch: refetchLogs } = useQuery<{ logs: string; lines: number }>({
    queryKey: ['cloud-backup-logs'],
    queryFn: () => api.get('/cloud-backup/logs?lines=200'),
    refetchInterval: () => status?.syncing ? 5000 : 30000,
  })
  const logContainerRef = useRef<HTMLDivElement>(null)

  // Fetch available dirs
  const { data: availableDirsData } = useQuery<{ dirs: string[] }>({
    queryKey: ['cloud-backup-available-dirs'],
    queryFn: () => api.get('/cloud-backup/available-dirs'),
  })

  // Fetch cloud storage status (cached, returns instantly)
  const { data: cloudStorage, refetch: refetchCloudStorage } = useQuery<CloudStorageStatus>({
    queryKey: ['cloud-backup-cloud-status'],
    queryFn: () => api.get('/cloud-backup/cloud-status'),
    enabled: !!status?.configured,
    refetchInterval: (query) => query.state.data?.query_running ? 5000 : false,
  })

  // Trigger background refresh
  const refreshCloudMutation = useMutation({
    mutationFn: () => api.post('/cloud-backup/cloud-status/refresh'),
    onSuccess: () => {
      setTimeout(() => refetchCloudStorage(), 1000)
    },
  })

  // Save config mutation
  const saveMutation = useMutation({
    mutationFn: (data: Partial<CloudBackupConfig>) =>
      api.put('/cloud-backup/config', data as Record<string, unknown>),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['cloud-backup-config'] })
      queryClient.invalidateQueries({ queryKey: ['cloud-backup-status'] })
      setHasChanges(false)
      notificationManager.success('Saved', 'Cloud backup configuration saved')
    },
    onError: (error: any) => {
      notificationManager.error('Error', error?.message || 'Failed to save configuration')
    },
  })

  // Sync now mutation
  const syncMutation = useMutation({
    mutationFn: () => api.post('/cloud-backup/sync'),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['cloud-backup-status'] })
      notificationManager.success('Sync', 'Sync started')
    },
    onError: (error: any) => {
      notificationManager.error('Sync Failed', error?.message || 'Failed to start sync')
    },
  })

  // Test connection mutation
  const testMutation = useMutation({
    mutationFn: () => api.post<{ status: string; message: string; remote_dirs?: string[] }>('/cloud-backup/test'),
    onSuccess: (data) => {
      if (data.status === 'success') {
        notificationManager.success('Connection Test', data.message)
      } else {
        notificationManager.error('Connection Test', data.message)
      }
    },
    onError: (error: any) => {
      notificationManager.error('Connection Test', error?.message || 'Connection test failed')
    },
  })

  // Pause/Resume mutations
  const pauseMutation = useMutation({
    mutationFn: () => api.post('/cloud-backup/pause'),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['cloud-backup-status'] })
      notificationManager.success('Service', 'Sync service stopped')
    },
  })
  const resumeMutation = useMutation({
    mutationFn: () => api.post('/cloud-backup/resume'),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['cloud-backup-status'] })
      notificationManager.success('Service', 'Sync service started')
    },
  })

  // Initialize form data when config loads
  useEffect(() => {
    if (config && !hasChanges) {
      setFormData(config)
    }
  }, [config, hasChanges])

  const updateField = (field: keyof CloudBackupConfig, value: any) => {
    setFormData(prev => ({ ...prev, [field]: value }))
    setHasChanges(true)
  }

  const handleSave = () => {
    saveMutation.mutate(formData)
  }

  const toggleIncludeDir = (dir: string) => {
    const current = formData.include_dirs || config?.include_dirs || []
    const updated = current.includes(dir) ? current.filter(d => d !== dir) : [...current, dir]
    updateField('include_dirs', updated)
  }

  if (configLoading) {
    return (
      <div className="flex items-center justify-center py-12">
        <Loader2 className="w-6 h-6 animate-spin text-blue-500" />
        <span className="ml-2 text-slate-500">Loading cloud backup settings...</span>
      </div>
    )
  }

  const serviceActive = status?.service_status === 'active'
  const isSyncing = status?.syncing || status?.state === 'syncing'
  const includeDirs = formData.include_dirs || config?.include_dirs || []
  const availableDirs = availableDirsData?.dirs || []

  return (
    <div className="space-y-6">
      {/* Section 1: Status Banner */}
      <div className="rounded-lg border border-slate-200 dark:border-slate-700 p-4 bg-slate-50 dark:bg-slate-800/50">
        <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
          <div className="flex items-center gap-3">
            <div className={`w-3 h-3 rounded-full ${
              isSyncing ? 'bg-blue-500 animate-pulse' :
              status?.state === 'error' ? 'bg-red-500' :
              serviceActive ? 'bg-green-500' :
              'bg-slate-400'
            }`} />
            <div>
              <span className="font-medium text-slate-900 dark:text-slate-100">
                {isSyncing ? 'Syncing...' :
                 status?.state === 'cooldown' ? 'Cooldown' :
                 serviceActive ? 'Watching for changes' :
                 status?.configured ? 'Service stopped' :
                 'Not configured'}
              </span>
              {status?.last_sync && (
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">
                  Last sync: {new Date(status.last_sync).toLocaleString()}
                  {status.last_sync_status === 'error' && <span className="text-red-500 ml-1">(errors)</span>}
                </p>
              )}
              {status?.active_job && (
                <div className="text-xs text-blue-500 mt-0.5 space-y-0.5">
                  <p>
                    Syncing {status.active_job.current_dir || '...'} ({status.active_job.dirs_synced}/{status.active_job.dirs_total} dirs)
                    {status.active_job.phase === 'checking' && (
                      <span className="text-yellow-500 ml-1.5">
                        — Comparing files{status.active_job.transfer_stats?.checks_done != null
                          ? ` (${status.active_job.transfer_stats.checks_done.toLocaleString()}${status.active_job.transfer_stats.checks_total ? ` / ${status.active_job.transfer_stats.checks_total.toLocaleString()}` : ''} checked)`
                          : '...'}
                      </span>
                    )}
                    {status.active_job.phase === 'preparing' && (
                      <span className="text-slate-400 ml-1.5">— Preparing...</span>
                    )}
                  </p>
                  {status.active_job.transfer_stats && status.active_job.phase === 'transferring' && (
                    <p className="text-blue-400">
                      {status.active_job.transfer_stats.bytes_done} / {status.active_job.transfer_stats.bytes_total}
                      {status.active_job.transfer_stats.pct != null && ` (${status.active_job.transfer_stats.pct}%)`}
                      {status.active_job.transfer_stats.speed && ` at ${status.active_job.transfer_stats.speed}`}
                      {status.active_job.transfer_stats.eta && ` — ETA ${status.active_job.transfer_stats.eta}`}
                      {status.active_job.transfer_stats.files_done != null && status.active_job.transfer_stats.files_total != null && (
                        <span className="text-slate-400 ml-1.5">
                          ({status.active_job.transfer_stats.files_done}/{status.active_job.transfer_stats.files_total} files)
                        </span>
                      )}
                    </p>
                  )}
                  {status.active_job.current_file && (
                    <p className="text-slate-400 truncate max-w-md">
                      {status.active_job.current_file}
                    </p>
                  )}
                </div>
              )}
              {status?.cooldown_remaining ? (
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">
                  Next sync in {status.cooldown_remaining}s
                </p>
              ) : null}
              {status?.storage_used != null && (
                <p className="text-xs text-slate-500 dark:text-slate-400">
                  Remote storage: {(status.storage_used / 1e12).toFixed(2)} TB
                </p>
              )}
              {status?.error_count ? (
                <p className="text-xs text-red-500">
                  {status.error_count} error{status.error_count > 1 ? 's' : ''}
                  {status.last_error && `: ${status.last_error.substring(0, 80)}`}
                </p>
              ) : null}
            </div>
          </div>
          <div className="flex gap-2 flex-wrap">
            <button
              onClick={() => syncMutation.mutate()}
              disabled={syncMutation.isPending || isSyncing || !status?.configured}
              className="px-3 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 flex items-center gap-1.5"
            >
              {syncMutation.isPending || isSyncing ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <RotateCw className="w-3.5 h-3.5" />}
              Sync Now
            </button>
            {serviceActive ? (
              <button
                onClick={() => pauseMutation.mutate()}
                disabled={pauseMutation.isPending}
                className="px-3 py-1.5 text-sm bg-amber-600 text-white rounded-lg hover:bg-amber-700 disabled:opacity-50 flex items-center gap-1.5"
              >
                <Pause className="w-3.5 h-3.5" />
                Pause
              </button>
            ) : (
              <button
                onClick={() => resumeMutation.mutate()}
                disabled={resumeMutation.isPending || !status?.configured}
                className="px-3 py-1.5 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 flex items-center gap-1.5"
              >
                <Play className="w-3.5 h-3.5" />
                Resume
              </button>
            )}
            <button
              onClick={() => testMutation.mutate()}
              disabled={testMutation.isPending || !status?.configured}
              className="px-3 py-1.5 text-sm bg-slate-600 text-white rounded-lg hover:bg-slate-700 disabled:opacity-50 flex items-center gap-1.5"
            >
              {testMutation.isPending ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <LinkIcon className="w-3.5 h-3.5" />}
              Test
            </button>
          </div>
        </div>
      </div>

      {/* Cloud Storage Status */}
      {status?.configured && (
        <div className="rounded-lg border border-slate-200 dark:border-slate-700 p-4">
          <div className="flex items-center justify-between mb-3">
            <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 flex items-center gap-2">
              <Cloud className="w-5 h-5 text-blue-500" />
              Cloud Storage
              {cloudStorage?.query_running && (
                <span className="text-xs font-normal text-blue-500 flex items-center gap-1">
                  <Loader2 className="w-3 h-3 animate-spin" /> Querying...
                </span>
              )}
            </h3>
            <div className="flex items-center gap-2">
              {cloudStorage?.queried_at && (
                <span className="text-xs text-slate-400">
                  {new Date(cloudStorage.queried_at).toLocaleString()}
                </span>
              )}
              <button
                onClick={() => refreshCloudMutation.mutate()}
                disabled={refreshCloudMutation.isPending || cloudStorage?.query_running}
                className="px-3 py-1.5 text-sm bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-lg hover:bg-slate-200 dark:hover:bg-slate-600 disabled:opacity-50 flex items-center gap-1.5"
              >
                {cloudStorage?.query_running ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <RefreshCw className="w-3.5 h-3.5" />}
                {cloudStorage?.queried_at ? 'Refresh' : 'Load Status'}
              </button>
            </div>
          </div>

          {!cloudStorage?.queried_at && !cloudStorage?.query_running && (
            <p className="text-sm text-slate-500 dark:text-slate-400">Click "Load Status" to query your cloud provider for current storage information.</p>
          )}

          {cloudStorage?.query_running && !cloudStorage?.total_files && (
            <div className="flex items-center gap-2 py-4 justify-center">
              <Loader2 className="w-5 h-5 animate-spin text-blue-500" />
              <span className="text-sm text-slate-500">Querying cloud provider (this may take a minute)...</span>
            </div>
          )}

          {cloudStorage && cloudStorage.queried_at && (
            <div className="space-y-4">
              {cloudStorage.error && (
                <div className="text-sm text-red-500 bg-red-50 dark:bg-red-900/20 rounded-lg p-3">
                  {cloudStorage.error}
                </div>
              )}

              {/* Summary row */}
              <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
                <div className="bg-slate-50 dark:bg-slate-800/50 rounded-lg p-3 text-center">
                  <div className="text-xl font-bold text-slate-900 dark:text-slate-100">
                    {cloudStorage.total_files != null ? cloudStorage.total_files.toLocaleString() : '—'}
                  </div>
                  <div className="text-xs text-slate-500 dark:text-slate-400">Total Files</div>
                </div>
                <div className="bg-slate-50 dark:bg-slate-800/50 rounded-lg p-3 text-center">
                  <div className="text-xl font-bold text-slate-900 dark:text-slate-100">
                    {cloudStorage.total_size_human || '—'}
                  </div>
                  <div className="text-xs text-slate-500 dark:text-slate-400">Total Size</div>
                </div>
                <div className="bg-slate-50 dark:bg-slate-800/50 rounded-lg p-3 text-center">
                  <div className="text-xl font-bold text-slate-900 dark:text-slate-100">
                    {cloudStorage.directories.length}
                  </div>
                  <div className="text-xs text-slate-500 dark:text-slate-400">Directories</div>
                </div>
                <div className="bg-slate-50 dark:bg-slate-800/50 rounded-lg p-3 text-center">
                  <div className="text-xl font-bold text-slate-900 dark:text-slate-100 flex items-center justify-center gap-1.5">
                    {cloudStorage.encryption ? (
                      <><Lock className="w-4 h-4 text-green-500" /> On</>
                    ) : (
                      <><Unlock className="w-4 h-4 text-amber-500" /> Off</>
                    )}
                  </div>
                  <div className="text-xs text-slate-500 dark:text-slate-400">Encryption</div>
                </div>
              </div>

              {/* Provider info */}
              <div className="text-xs text-slate-500 dark:text-slate-400 flex flex-wrap gap-x-4 gap-y-1">
                <span>Provider: <span className="text-slate-700 dark:text-slate-300">{cloudStorage.provider === 'b2' ? 'Backblaze B2' : 'S3-Compatible'}</span></span>
                <span>Bucket: <span className="text-slate-700 dark:text-slate-300">{cloudStorage.bucket}</span></span>
                <span>Endpoint: <span className="text-slate-700 dark:text-slate-300">{cloudStorage.endpoint}</span></span>
              </div>

              {/* Per-directory breakdown */}
              {cloudStorage.directories.length > 0 && (
                <div>
                  <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Directory Breakdown</h4>
                  <div className="overflow-hidden rounded-lg border border-slate-200 dark:border-slate-700">
                    <table className="w-full text-sm">
                      <thead>
                        <tr className="bg-slate-50 dark:bg-slate-800/50 text-left">
                          <th className="px-3 py-2 font-medium text-slate-600 dark:text-slate-400">Directory</th>
                          <th className="px-3 py-2 font-medium text-slate-600 dark:text-slate-400 text-right">Files</th>
                          <th className="px-3 py-2 font-medium text-slate-600 dark:text-slate-400 text-right">Size</th>
                          <th className="px-3 py-2 font-medium text-slate-600 dark:text-slate-400 text-right w-24">% of Total</th>
                        </tr>
                      </thead>
                      <tbody className="divide-y divide-slate-200 dark:divide-slate-700">
                        {cloudStorage.directories
                          .sort((a, b) => b.size - a.size)
                          .map((dir) => {
                            const pct = cloudStorage.total_size ? ((dir.size / cloudStorage.total_size) * 100) : 0
                            return (
                              <tr key={dir.name} className="hover:bg-slate-50 dark:hover:bg-slate-800/30">
                                <td className="px-3 py-1.5 font-mono text-slate-900 dark:text-slate-100">{dir.name}</td>
                                <td className="px-3 py-1.5 text-right text-slate-600 dark:text-slate-400">{dir.files.toLocaleString()}</td>
                                <td className="px-3 py-1.5 text-right text-slate-600 dark:text-slate-400">{dir.size_human}</td>
                                <td className="px-3 py-1.5 text-right">
                                  <div className="flex items-center gap-2 justify-end">
                                    <div className="w-12 h-1.5 bg-slate-200 dark:bg-slate-700 rounded-full overflow-hidden">
                                      <div className="h-full bg-blue-500 rounded-full" style={{ width: `${Math.min(pct, 100)}%` }} />
                                    </div>
                                    <span className="text-xs text-slate-500 w-10 text-right">{pct.toFixed(1)}%</span>
                                  </div>
                                </td>
                              </tr>
                            )
                          })}
                      </tbody>
                    </table>
                  </div>
                </div>
              )}
            </div>
          )}
        </div>
      )}

      {/* Section 2: Provider Settings */}
      <div>
        <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-4">Provider Settings</h3>
        <div className="space-y-4">
          {/* Enable toggle */}
          <div className="flex items-center justify-between">
            <div>
              <label className="font-medium text-slate-900 dark:text-slate-100">Enable Cloud Backup</label>
              <p className="text-xs text-slate-500 dark:text-slate-400">Automatically sync media files to cloud storage</p>
            </div>
            <button
              onClick={() => updateField('enabled', !formData.enabled)}
              className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
                formData.enabled ? 'bg-blue-600' : 'bg-slate-300 dark:bg-slate-600'
              }`}
            >
              <span className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                formData.enabled ? 'translate-x-6' : 'translate-x-1'
              }`} />
            </button>
          </div>

          {/* Provider */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Provider</label>
            <select
              value={formData.provider || 'b2'}
              onChange={(e) => updateField('provider', e.target.value)}
              className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
            >
              <option value="b2">Backblaze B2</option>
              <option value="s3">S3-Compatible</option>
            </select>
          </div>

          {/* Endpoint */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Endpoint</label>
            <input
              type="text"
              value={formData.endpoint || ''}
              onChange={(e) => updateField('endpoint', e.target.value)}
              placeholder="s3.us-west-000.backblazeb2.com"
              className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
            />
          </div>

          {/* Bucket */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Bucket</label>
            <input
              type="text"
              value={formData.bucket || ''}
              onChange={(e) => updateField('bucket', e.target.value)}
              placeholder="my-backup-bucket"
              className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
            />
          </div>

          {/* Key ID */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Key ID</label>
            <input
              type={showPasswords ? 'text' : 'password'}
              value={formData.key_id || ''}
              onChange={(e) => updateField('key_id', e.target.value)}
              placeholder="Key ID"
              className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
            />
          </div>

          {/* Application Key */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Application Key</label>
            <div className="flex gap-2">
              <input
                type={showPasswords ? 'text' : 'password'}
                value={formData.application_key || ''}
                onChange={(e) => updateField('application_key', e.target.value)}
                placeholder="Application Key"
                className="flex-1 px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
              />
              <button
                onClick={() => setShowPasswords(!showPasswords)}
                className="px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700"
                title={showPasswords ? 'Hide passwords' : 'Show passwords'}
              >
                {showPasswords ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
              </button>
            </div>
          </div>
        </div>
      </div>

      {/* Section 3: Encryption & Sync Settings */}
      <div className="border-t border-slate-200 dark:border-slate-700 pt-6">
        <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-4">Encryption & Sync Settings</h3>
        <div className="space-y-4">
          {/* Encryption toggle */}
          <div className="flex items-center justify-between">
            <div>
              <label className="font-medium text-slate-900 dark:text-slate-100">Encrypt files (AES-256)</label>
              <p className="text-xs text-slate-500 dark:text-slate-400">Encrypt filenames and contents before uploading</p>
            </div>
            <button
              onClick={() => updateField('encryption_enabled', !formData.encryption_enabled)}
              className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
                formData.encryption_enabled !== false ? 'bg-blue-600' : 'bg-slate-300 dark:bg-slate-600'
              }`}
            >
              <span className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                formData.encryption_enabled !== false ? 'translate-x-6' : 'translate-x-1'
              }`} />
            </button>
          </div>

          {formData.encryption_enabled !== false && (
            <>
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Encryption Password</label>
                <input
                  type={showPasswords ? 'text' : 'password'}
                  value={formData.encryption_password || ''}
                  onChange={(e) => updateField('encryption_password', e.target.value)}
                  placeholder="Encryption password"
                  className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
                />
              </div>
              <div>
                <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Encryption Salt</label>
                <input
                  type={showPasswords ? 'text' : 'password'}
                  value={formData.encryption_salt || ''}
                  onChange={(e) => updateField('encryption_salt', e.target.value)}
                  placeholder="Encryption salt"
                  className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
                />
              </div>
            </>
          )}

          {/* Sync scope: checkboxes for directories */}
          <div>
            <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Directories to Back Up</label>
            <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
              {availableDirs.map(dir => (
                <label key={dir} className="flex items-center gap-2 text-sm text-slate-700 dark:text-slate-300 cursor-pointer">
                  <input
                    type="checkbox"
                    checked={includeDirs.includes(dir)}
                    onChange={() => toggleIncludeDir(dir)}
                    className="rounded border-slate-300 text-blue-600 focus:ring-blue-500"
                  />
                  {dir}
                </label>
              ))}
            </div>
          </div>

          {/* Cooldown */}
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Cooldown (seconds)</label>
              <input
                type="number"
                value={formData.cooldown_seconds ?? 300}
                onChange={(e) => updateField('cooldown_seconds', parseInt(e.target.value) || 300)}
                min={30}
                className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
              />
              <p className="text-xs text-slate-500 mt-1">Wait this long after last file change before syncing</p>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Bandwidth Limit</label>
              <input
                type="text"
                value={formData.bandwidth_limit || ''}
                onChange={(e) => updateField('bandwidth_limit', e.target.value || null)}
                placeholder="e.g. 10M (empty = unlimited)"
                className="w-full px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg text-sm"
              />
              <p className="text-xs text-slate-500 mt-1">rclone format: 10M = 10MB/s</p>
            </div>
          </div>
        </div>
      </div>

      {/* Save button */}
      <div className="flex justify-end">
        <button
          onClick={handleSave}
          disabled={!hasChanges || saveMutation.isPending}
          className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 flex items-center gap-2"
        >
          {saveMutation.isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
          Save Configuration
        </button>
      </div>

      {/* Section 4: Sync Log */}
      <div className="border-t border-slate-200 dark:border-slate-700 pt-6">
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 flex items-center gap-2">
            Sync Log
            {isSyncing && <span className="text-xs font-normal text-blue-500 flex items-center gap-1"><Loader2 className="w-3 h-3 animate-spin" /> Live</span>}
          </h3>
          <button
            onClick={() => refetchLogs()}
            className="px-2 py-1 text-xs text-slate-500 hover:text-slate-700 dark:hover:text-slate-300 flex items-center gap-1"
          >
            <RefreshCw className="w-3 h-3" />
            Refresh
          </button>
        </div>
        <div ref={logContainerRef} className="bg-slate-900 rounded-lg p-4 max-h-80 overflow-y-auto">
          <pre className="text-xs text-slate-300 font-mono whitespace-pre-wrap break-all">
            {logsData?.logs
              ? logsData.logs.trim().split('\n')
                  .filter(l => !l.includes('[progress]'))
                  .reverse()
                  .join('\n')
              : 'No logs yet. Logs will appear here once a sync runs.'}
          </pre>
        </div>
      </div>
    </div>
  )
}


// 2. Update the features list to reflect new/removed features
// 3. Update version in App.tsx (2 locations: desktop and mobile menu)
// 4. Update version in package.json
//
function AboutTab() {
  return (
    <div className="space-y-6">
      <div className="text-center py-8">
        <div className="inline-flex items-center justify-center w-20 h-20 bg-blue-600 rounded-full mb-4">
          <Download className="w-10 h-10 text-white" />
        </div>
        <h2 className="text-2xl font-bold text-slate-900 dark:text-slate-100 mb-2">
          Media Downloader
        </h2>
        <p className="text-slate-600 dark:text-slate-400 mb-1">Version 13.13.1</p>
        <p className="text-sm text-slate-500 dark:text-slate-500">
          Built with React, FastAPI, and Python
        </p>
      </div>

      <div className="border-t border-slate-200 dark:border-slate-700 pt-6">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-3">Features</h3>
        <ul className="space-y-2 text-sm text-slate-600 dark:text-slate-400">
          <li className="flex items-center space-x-2">
            <CheckCircle className="w-4 h-4 text-green-600" />
            <span>Multi-platform media downloading (Instagram, TikTok, Snapchat, Forums)</span>
          </li>
          <li className="flex items-center space-x-2">
            <CheckCircle className="w-4 h-4 text-green-600" />
            <span>Automated scheduling and monitoring</span>
          </li>
          <li className="flex items-center space-x-2">
            <CheckCircle className="w-4 h-4 text-green-600" />
            <span>Advanced duplicate detection</span>
          </li>
          <li className="flex items-center space-x-2">
            <CheckCircle className="w-4 h-4 text-green-600" />
            <span>2FA authentication (TOTP & Duo)</span>
          </li>
          <li className="flex items-center space-x-2">
            <CheckCircle className="w-4 h-4 text-green-600" />
            <span>Real-time analytics and reporting</span>
          </li>
          <li className="flex items-center space-x-2">
            <CheckCircle className="w-4 h-4 text-green-600" />
            <span>In-app toast notifications</span>
          </li>
        </ul>
      </div>

      <div className="border-t border-slate-200 dark:border-slate-700 pt-6">
        <h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-3">System Information</h3>
        <div className="grid grid-cols-2 gap-4 text-sm">
          <div>
            <p className="text-slate-500 dark:text-slate-400">Python Version</p>
            <p className="text-slate-900 dark:text-slate-100 font-mono">3.12+</p>
          </div>
          <div>
            <p className="text-slate-500 dark:text-slate-400">Database</p>
            <p className="text-slate-900 dark:text-slate-100 font-mono">SQLite</p>
          </div>
          <div>
            <p className="text-slate-500 dark:text-slate-400">API Framework</p>
            <p className="text-slate-900 dark:text-slate-100 font-mono">FastAPI</p>
          </div>
          <div>
            <p className="text-slate-500 dark:text-slate-400">UI Framework</p>
            <p className="text-slate-900 dark:text-slate-100 font-mono">React + TypeScript</p>
          </div>
        </div>
      </div>
    </div>
  )
}

// Features Tab - Inline password authentication, no redirect
const FEATURE_GROUPS = [
  {
    id: 'media',
    label: 'Media',
    icon: Download,
    items: [
      { path: '/downloads', label: 'Downloads', icon: Download },
      { path: '/gallery', label: 'Gallery', icon: Film },
      { path: '/review', label: 'Review', icon: CheckCircle },
    ]
  },
  {
    id: 'video',
    label: 'Video',
    icon: Film,
    items: [
      { path: '/videos', label: 'Video Downloader', icon: Film },
      { path: '/celebrities', label: 'Internet Discovery', icon: Users },
      { path: '/queue', label: 'Download Queue', icon: ListVideo },
      { path: '/video/channel-monitors', label: 'Channel Monitors', icon: Film },
    ]
  },
  {
    id: 'tools',
    label: 'Tools',
    icon: Wrench,
    items: [
      { path: '/import', label: 'Manual Import', icon: FolderInput },
      { path: '/faces', label: 'Face Recognition', icon: User },
      { path: '/scheduler', label: 'Scheduler', icon: Clock },
      { path: '/appearances', label: 'Appearances', icon: User },
      { path: '/press', label: 'Press', icon: Newspaper },
      { path: '/discovery', label: 'Discovery', icon: Search },
      { path: '/recycle-bin', label: 'Recycle Bin', icon: Trash2 },
    ]
  },
  {
    id: 'analytics',
    label: 'Analytics',
    icon: Settings,
    items: [
      { path: '/analytics', label: 'Analytics', icon: Settings },
      { path: '/health', label: 'System Health', icon: Heart },
      { path: '/monitoring', label: 'Monitoring', icon: Settings },
      { path: '/notifications', label: 'Notifications', icon: Settings },
    ]
  },
  {
    id: 'paid-content',
    label: 'Paid Content',
    icon: CreditCard,
    items: [
      { path: '/paid-content', label: 'Dashboard', icon: CreditCard },
      { path: '/paid-content/feed', label: 'Feed', icon: FileText },
      { path: '/paid-content/messages', label: 'Messages', icon: MessageCircle },
      { path: '/paid-content/creators', label: 'Creators', icon: Users },
      { path: '/paid-content/add', label: 'Add Content', icon: Settings },
      { path: '/paid-content/queue', label: 'Download Queue', icon: ListVideo },
      { path: '/paid-content/notifications', label: 'Notifications', icon: Settings },
      { path: '/paid-content/settings', label: 'Configuration', icon: Settings },
    ]
  },
  {
    id: 'private-gallery',
    label: 'Private Gallery',
    icon: Lock,
    items: [
      { path: '/private-gallery', label: 'Gallery', icon: Lock },
      { path: '/private-gallery/config', label: 'Settings', icon: Settings },
    ]
  },
  {
    id: 'system',
    label: 'System',
    icon: Settings,
    items: [
      { path: '/config', label: 'Configuration', icon: Settings },
      { path: '/platforms', label: 'Platforms', icon: Layers },
      { path: '/scrapers', label: 'Scrapers', icon: Settings },
      { path: '/logs', label: 'Logs', icon: FileText },
      { path: '/changelog', label: 'Change Log', icon: FileText },
    ]
  },
]

function ModulesTab() {
  const { data: config } = useQuery({
    queryKey: ['config'],
    queryFn: () => api.getConfig(),
  })
  const queryClient = useQueryClient()
  const [editedHiddenModules, setEditedHiddenModules] = useState<string[]>([])
  const [hasChanges, setHasChanges] = useState(false)

  useEffect(() => {
    if (config) {
      setEditedHiddenModules((config.hidden_modules as string[]) || [])
    }
  }, [config])

  const allModules = [
    { id: 'tiktok', name: 'TikTok', description: 'TikTok video downloader', icon: 'TT', bgColor: 'bg-black' },
    { id: 'instagram', name: 'InstaLoader', description: 'Instagram via Instaloader sessions', icon: 'IG', bgColor: 'bg-gradient-to-r from-purple-600 to-pink-600' },
    { id: 'fastdl', name: 'FastDL', description: 'Instagram via FastDL (Playwright)', icon: 'FD', bgColor: 'bg-blue-600' },
    { id: 'imginn', name: 'ImgInn', description: 'Instagram via ImgInn (Playwright)', icon: 'II', bgColor: 'bg-indigo-600' },
    { id: 'imginn_api', name: 'ImgInn API', description: 'Instagram via ImgInn API (no browser)', icon: 'IA', bgColor: 'bg-violet-600' },
    { id: 'instagram_client', name: 'Instagram (API)', description: 'Instagram via direct API (no browser)', icon: 'IC', bgColor: 'bg-gradient-to-r from-purple-500 to-indigo-600' },
    { id: 'toolzu', name: 'Toolzu', description: 'Instagram 1920x1440 resolution (Playwright)', icon: 'TZ', bgColor: 'bg-cyan-600' },
    { id: 'snapchat', name: 'Snapchat', description: 'Snapchat via Playwright browser', icon: 'SC', bgColor: 'bg-yellow-400' },
    { id: 'snapchat_client', name: 'Snapchat (API)', description: 'Snapchat via direct HTTP (no browser)', icon: 'SA', bgColor: 'bg-gradient-to-r from-yellow-400 to-orange-500' },
    { id: 'forums', name: 'Forums', description: 'Forum thread scraping and monitoring', icon: 'FR', bgColor: 'bg-green-600' },
    { id: 'coppermine', name: 'Coppermine', description: 'Coppermine photo gallery downloader', icon: 'CP', bgColor: 'bg-orange-600' },
    { id: 'youtube_monitors', name: 'YouTube Monitors', description: 'YouTube channel monitoring', icon: 'YT', bgColor: 'bg-red-600' },
  ]

  const toggleModule = (moduleId: string) => {
    setEditedHiddenModules(prev => {
      const newHidden = prev.includes(moduleId)
        ? prev.filter(id => id !== moduleId)
        : [...prev, moduleId]
      setHasChanges(true)
      return newHidden
    })
  }

  const updateMutation = useMutation({
    mutationFn: (newConfig: any) => api.updateConfig(newConfig),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['config'] })
      setHasChanges(false)
    },
  })

  const saveModules = async () => {
    try {
      const updatedConfig: Record<string, any> = { ...config, hidden_modules: editedHiddenModules }
      // Also disable hidden modules
      for (const moduleId of editedHiddenModules) {
        if (updatedConfig[moduleId]) {
          updatedConfig[moduleId] = { ...updatedConfig[moduleId], enabled: false }
        }
      }
      updateMutation.mutate(updatedConfig)
    } catch (err) {
      console.error('Failed to save module settings:', err)
    }
  }

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100">Module Management</h3>
          <p className="text-sm text-slate-500 dark:text-slate-400">Enable or disable modules globally. Disabled modules are hidden from Configuration, Scheduler, and Dashboard.</p>
        </div>
        {hasChanges && (
          <button
            onClick={saveModules}
            className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium"
          >
            Save Changes
          </button>
        )}
      </div>
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
        {allModules.map((mod) => {
          const isEnabled = !editedHiddenModules.includes(mod.id)
          return (
            <div
              key={mod.id}
              className={`rounded-xl border transition-all ${
                isEnabled
                  ? 'border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800'
                  : 'border-slate-200/50 dark:border-slate-700/50 bg-slate-50 dark:bg-slate-900 opacity-60'
              }`}
            >
              <div className="p-4 flex items-center justify-between">
                <div className="flex items-center space-x-3">
                  <div className={`w-8 h-8 ${mod.bgColor} rounded-lg flex items-center justify-center text-white text-xs font-bold`}>
                    {mod.icon}
                  </div>
                  <div>
                    <h4 className="text-sm font-medium text-slate-900 dark:text-slate-100">{mod.name}</h4>
                    <p className="text-xs text-slate-500 dark:text-slate-400">{mod.description}</p>
                  </div>
                </div>
                <label className="relative inline-flex items-center cursor-pointer">
                  <input
                    type="checkbox"
                    checked={isEnabled}
                    onChange={() => toggleModule(mod.id)}
                    className="sr-only peer"
                  />
                  <div className="w-9 h-5 bg-slate-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-slate-600 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:after:border-slate-600 peer-checked:bg-blue-600"></div>
                </label>
              </div>
            </div>
          )
        })}
      </div>
    </div>
  )
}

function FeaturesTab() {
  const [isAuthenticated, setIsAuthenticated] = useState(false)
  const [isSetupComplete, setIsSetupComplete] = useState<boolean | null>(null)
  const [isCheckingStatus, setIsCheckingStatus] = useState(true)
  const [password, setPassword] = useState('')
  const [authError, setAuthError] = useState('')
  const [isAuthenticating, setIsAuthenticating] = useState(false)
  const [enabledFeatures, setEnabledFeatures] = useState<string[]>([])
  const [featureOrder, setFeatureOrder] = useState<Record<string, string[]>>({})
  const [featureLabels, setFeatureLabels] = useState<Record<string, string>>({})
  const [groupOrder, setGroupOrder] = useState<string[]>([])
  const [isSaving, setIsSaving] = useState(false)
  const [isResetting, setIsResetting] = useState(false)
  const [hasChanges, setHasChanges] = useState(false)
  const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set(FEATURE_GROUPS.map(g => g.id)))
  const [draggedItem, setDraggedItem] = useState<{ groupId: string; index: number } | null>(null)
  const [draggedGroup, setDraggedGroup] = useState<string | null>(null)
  const [searchQuery, setSearchQuery] = useState('')
  const [editingLabel, setEditingLabel] = useState<string | null>(null)
  const [editLabelValue, setEditLabelValue] = useState('')
  const queryClient = useQueryClient()

  // Unsaved changes warning
  useEffect(() => {
    const handleBeforeUnload = (e: BeforeUnloadEvent) => {
      if (hasChanges) {
        e.preventDefault()
        e.returnValue = ''
      }
    }
    window.addEventListener('beforeunload', handleBeforeUnload)
    return () => window.removeEventListener('beforeunload', handleBeforeUnload)
  }, [hasChanges])

  // Check status and try to authenticate using existing session
  useEffect(() => {
    const checkStatusAndSession = async () => {
      setIsCheckingStatus(true)
      try {
        // First check if private gallery is set up
        const status = await api.privateGallery.getStatus()
        setIsSetupComplete(status.is_setup_complete)

        if (!status.is_setup_complete) {
          setIsCheckingStatus(false)
          return
        }

        // If setup complete, check for existing session
        const token = sessionStorage.getItem('privateGalleryToken')
        if (token) {
          try {
            const response = await api.privateGallery.getFeatures()
            setEnabledFeatures(response.enabled_features)
            setFeatureOrder(response.feature_order || {})
            setFeatureLabels(response.feature_labels || {})
            setGroupOrder(response.group_order || [])
            setIsAuthenticated(true)
          } catch {
            sessionStorage.removeItem('privateGalleryToken')
          }
        }
      } catch (error: unknown) {
        const err = error as { message?: string }
        console.error('Failed to check private gallery status:', error)
        // Show the actual error instead of assuming not set up
        setAuthError(`Failed to check status: ${err.message || 'Unknown error'}`)
        setIsSetupComplete(true) // Assume set up, let user try to authenticate
      } finally {
        setIsCheckingStatus(false)
      }
    }
    checkStatusAndSession()
  }, [])

  const handleAuthenticate = async (e: React.FormEvent) => {
    e.preventDefault()
    setIsAuthenticating(true)
    setAuthError('')

    try {
      const response = await api.privateGallery.unlock(password)
      sessionStorage.setItem('privateGalleryToken', response.token)

      // Fetch features after successful auth
      const featuresResponse = await api.privateGallery.getFeatures()
      setEnabledFeatures(featuresResponse.enabled_features)
      setFeatureOrder(featuresResponse.feature_order || {})
      setFeatureLabels(featuresResponse.feature_labels || {})
      setGroupOrder(featuresResponse.group_order || [])
      setIsAuthenticated(true)
      setPassword('')
    } catch (error: unknown) {
      const err = error as { message?: string }
      setAuthError(err.message || 'Invalid password')
    } finally {
      setIsAuthenticating(false)
    }
  }

  const handleToggleFeature = (path: string) => {
    setEnabledFeatures(prev => {
      const newEnabled = prev.includes(path)
        ? prev.filter(p => p !== path)
        : [...prev, path]
      setHasChanges(true)
      return newEnabled
    })
  }

  const handleToggleGroup = (groupId: string) => {
    const group = FEATURE_GROUPS.find(g => g.id === groupId)
    if (!group) return

    const groupPaths = group.items.map(item => item.path)
    const allEnabled = groupPaths.every(path => enabledFeatures.includes(path))

    setEnabledFeatures(prev => {
      if (allEnabled) {
        // Disable all in group
        return prev.filter(p => !groupPaths.includes(p))
      } else {
        // Enable all in group
        const newEnabled = new Set([...prev, ...groupPaths])
        return Array.from(newEnabled)
      }
    })
    setHasChanges(true)
  }

  const handleExpandToggle = (groupId: string) => {
    setExpandedGroups(prev => {
      const newSet = new Set(prev)
      if (newSet.has(groupId)) {
        newSet.delete(groupId)
      } else {
        newSet.add(groupId)
      }
      return newSet
    })
  }

  const handleDragStart = (e: React.DragEvent, groupId: string, index: number) => {
    setDraggedItem({ groupId, index })
    e.dataTransfer.effectAllowed = 'move'
  }

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault()
    e.dataTransfer.dropEffect = 'move'
  }

  const handleDrop = (e: React.DragEvent, groupId: string, targetIndex: number) => {
    e.preventDefault()
    if (!draggedItem || draggedItem.groupId !== groupId) return

    const group = FEATURE_GROUPS.find(g => g.id === groupId)
    if (!group) return

    const currentOrder = featureOrder[groupId] || group.items.map(item => item.path)
    const newOrder = [...currentOrder]
    const [movedItem] = newOrder.splice(draggedItem.index, 1)
    newOrder.splice(targetIndex, 0, movedItem)

    setFeatureOrder(prev => ({ ...prev, [groupId]: newOrder }))
    setHasChanges(true)
    setDraggedItem(null)
  }

  const handleDragEnd = () => {
    setDraggedItem(null)
  }

  const handleSave = async () => {
    setIsSaving(true)
    try {
      await api.privateGallery.updateFeatures({
        enabled_features: enabledFeatures,
        feature_order: featureOrder,
        feature_labels: featureLabels,
        group_order: groupOrder,
      })
      setHasChanges(false)
      // Invalidate the enabled-features query so the sidebar updates
      queryClient.invalidateQueries({ queryKey: ['enabled-features'] })
    } catch (error) {
      console.error('Failed to save features:', error)
      alert('Failed to save features')
    } finally {
      setIsSaving(false)
    }
  }

  const handleReset = async () => {
    if (!confirm('Reset all feature settings to defaults? This will enable all features and clear custom labels.')) {
      return
    }
    setIsResetting(true)
    try {
      const response = await api.privateGallery.resetFeatures()
      setEnabledFeatures(response.enabled_features)
      setFeatureOrder(response.feature_order || {})
      setFeatureLabels(response.feature_labels || {})
      setGroupOrder(response.group_order || [])
      setHasChanges(false)
      queryClient.invalidateQueries({ queryKey: ['enabled-features'] })
    } catch (error) {
      console.error('Failed to reset features:', error)
      alert('Failed to reset features')
    } finally {
      setIsResetting(false)
    }
  }

  const handleLabelEdit = (path: string) => {
    const group = FEATURE_GROUPS.find(g => g.items.some(i => i.path === path))
    const item = group?.items.find(i => i.path === path)
    setEditingLabel(path)
    setEditLabelValue(featureLabels[path] || item?.label || '')
  }

  const handleLabelSave = (path: string) => {
    const group = FEATURE_GROUPS.find(g => g.items.some(i => i.path === path))
    const item = group?.items.find(i => i.path === path)
    const defaultLabel = item?.label || ''

    if (editLabelValue.trim() === '' || editLabelValue === defaultLabel) {
      // Remove custom label if empty or same as default
      setFeatureLabels(prev => {
        const newLabels = { ...prev }
        delete newLabels[path]
        return newLabels
      })
    } else {
      setFeatureLabels(prev => ({ ...prev, [path]: editLabelValue.trim() }))
    }
    setEditingLabel(null)
    setHasChanges(true)
  }

  const handleExpandAll = () => {
    setExpandedGroups(new Set(FEATURE_GROUPS.map(g => g.id)))
  }

  const handleCollapseAll = () => {
    setExpandedGroups(new Set())
  }

  const handleGroupDragStart = (e: React.DragEvent, groupId: string) => {
    setDraggedGroup(groupId)
    e.dataTransfer.effectAllowed = 'move'
  }

  const handleGroupDrop = (e: React.DragEvent, targetGroupId: string) => {
    e.preventDefault()
    if (!draggedGroup || draggedGroup === targetGroupId) return

    const currentOrder = groupOrder.length > 0 ? groupOrder : FEATURE_GROUPS.map(g => g.id)
    const dragIndex = currentOrder.indexOf(draggedGroup)
    const targetIndex = currentOrder.indexOf(targetGroupId)

    const newOrder = [...currentOrder]
    newOrder.splice(dragIndex, 1)
    newOrder.splice(targetIndex, 0, draggedGroup)

    setGroupOrder(newOrder)
    setHasChanges(true)
    setDraggedGroup(null)
  }

  const handleGroupDragEnd = () => {
    setDraggedGroup(null)
  }

  const handleEnableAll = () => {
    const allPaths = FEATURE_GROUPS.flatMap(g => g.items.map(i => i.path))
    setEnabledFeatures(allPaths)
    setHasChanges(true)
  }

  const handleDisableAll = () => {
    setEnabledFeatures([])
    setHasChanges(true)
  }

  const getOrderedItems = (groupId: string) => {
    const group = FEATURE_GROUPS.find(g => g.id === groupId)
    if (!group) return []

    const order = featureOrder[groupId]
    if (!order || order.length === 0) return group.items

    return [...group.items].sort((a, b) => {
      const aIndex = order.indexOf(a.path)
      const bIndex = order.indexOf(b.path)
      const aPos = aIndex === -1 ? 9999 : aIndex
      const bPos = bIndex === -1 ? 9999 : bIndex
      return aPos - bPos
    })
  }

  const getOrderedGroups = () => {
    if (!groupOrder || groupOrder.length === 0) return FEATURE_GROUPS

    return [...FEATURE_GROUPS].sort((a, b) => {
      const aIndex = groupOrder.indexOf(a.id)
      const bIndex = groupOrder.indexOf(b.id)
      const aPos = aIndex === -1 ? 9999 : aIndex
      const bPos = bIndex === -1 ? 9999 : bIndex
      return aPos - bPos
    })
  }

  const getFilteredGroups = () => {
    if (!searchQuery.trim()) return getOrderedGroups()

    const query = searchQuery.toLowerCase()
    return getOrderedGroups().map(group => ({
      ...group,
      items: group.items.filter(item =>
        item.label.toLowerCase().includes(query) ||
        item.path.toLowerCase().includes(query) ||
        (featureLabels[item.path] || '').toLowerCase().includes(query)
      )
    })).filter(group => group.items.length > 0)
  }

  const getDisplayLabel = (path: string, defaultLabel: string) => {
    return featureLabels[path] || defaultLabel
  }

  // Show loading while checking status
  if (isCheckingStatus) {
    return (
      <div className="flex items-center justify-center py-12">
        <Loader2 className="w-8 h-8 animate-spin text-indigo-600" />
      </div>
    )
  }

  // Show setup required message if private gallery is not set up
  if (!isSetupComplete) {
    return (
      <div className="space-y-6">
        <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
          <div className="flex items-start gap-3">
            <Lock className="w-5 h-5 text-blue-600 dark:text-blue-400 mt-0.5" />
            <div>
              <h3 className="font-medium text-blue-900 dark:text-blue-100">Setup Required</h3>
              <p className="text-sm text-blue-700 dark:text-blue-300 mt-1">
                The Private Gallery needs to be set up before you can manage features.
                Please visit the Private Gallery to create a password first.
              </p>
              <Link
                to="/private-gallery"
                className="inline-flex items-center gap-2 mt-3 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 text-sm"
              >
                <Lock className="w-4 h-4" />
                Go to Private Gallery Setup
              </Link>
            </div>
          </div>
        </div>
      </div>
    )
  }

  // Show password prompt if not authenticated
  if (!isAuthenticated) {
    return (
      <div className="space-y-6">
        <div className="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4">
          <div className="flex items-start gap-3">
            <Lock className="w-5 h-5 text-amber-600 dark:text-amber-400 mt-0.5" />
            <div>
              <h3 className="font-medium text-amber-900 dark:text-amber-100">Authentication Required</h3>
            </div>
          </div>
        </div>

        <form onSubmit={handleAuthenticate} className="max-w-md">
          <div className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
                Password
              </label>
              <input
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
                placeholder="Enter password"
                autoFocus
              />
            </div>
            {authError && (
              <p className="text-sm text-red-600 dark:text-red-400">{authError}</p>
            )}
            <button
              type="submit"
              disabled={isAuthenticating || !password}
              className="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
            >
              {isAuthenticating ? (
                <>
                  <Loader2 className="w-4 h-4 animate-spin" />
                  Authenticating...
                </>
              ) : (
                <>
                  <Lock className="w-4 h-4" />
                  Unlock
                </>
              )}
            </button>
          </div>
        </form>
      </div>
    )
  }

  return (
    <div className="space-y-6">
      {/* Header with actions */}
      <div className="flex flex-col gap-4">
        <div className="flex items-center justify-between">
          <div>
            <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100">Feature Management</h3>
            <p className="text-sm text-slate-600 dark:text-slate-400 mt-1">
              Enable/disable menu items. Drag to reorder. Double-click labels to rename.
            </p>
          </div>
          <div className="flex items-center gap-2">
            <button
              onClick={handleReset}
              disabled={isResetting}
              className="px-3 py-1.5 text-sm text-slate-600 dark:text-slate-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors flex items-center gap-1"
              title="Reset to defaults"
            >
              {isResetting ? <Loader2 className="w-4 h-4 animate-spin" /> : <RefreshCcw className="w-4 h-4" />}
              Reset
            </button>
            <button
              onClick={handleSave}
              disabled={!hasChanges || isSaving}
              className="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
            >
              {isSaving ? (
                <>
                  <Loader2 className="w-4 h-4 animate-spin" />
                  Saving...
                </>
              ) : (
                <>
                  <Save className="w-4 h-4" />
                  Save Changes
                </>
              )}
            </button>
          </div>
        </div>

        {/* Search and quick actions */}
        <div className="flex items-center gap-4">
          <div className="relative flex-1 max-w-xs">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
            <input
              type="text"
              placeholder="Search features..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              className="w-full pl-9 pr-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
            />
          </div>
          <div className="flex items-center gap-1 border-l border-slate-200 dark:border-slate-700 pl-4">
            <button
              onClick={handleExpandAll}
              className="px-2 py-1 text-xs text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100 hover:bg-slate-100 dark:hover:bg-slate-800 rounded transition-colors"
            >
              Expand All
            </button>
            <button
              onClick={handleCollapseAll}
              className="px-2 py-1 text-xs text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100 hover:bg-slate-100 dark:hover:bg-slate-800 rounded transition-colors"
            >
              Collapse All
            </button>
          </div>
          <div className="flex items-center gap-1 border-l border-slate-200 dark:border-slate-700 pl-4">
            <button
              onClick={handleEnableAll}
              className="px-2 py-1 text-xs text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100 hover:bg-slate-100 dark:hover:bg-slate-800 rounded transition-colors"
            >
              Enable All
            </button>
            <button
              onClick={handleDisableAll}
              className="px-2 py-1 text-xs text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100 hover:bg-slate-100 dark:hover:bg-slate-800 rounded transition-colors"
            >
              Disable All
            </button>
          </div>
        </div>
      </div>

      {hasChanges && (
        <div className="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-3">
          <p className="text-sm text-amber-700 dark:text-amber-300">
            You have unsaved changes. Click "Save Changes" to apply them.
          </p>
        </div>
      )}

      {/* Feature groups */}
      <div className="space-y-4">
        {getFilteredGroups().length === 0 ? (
          <div className="text-center py-8 text-slate-500 dark:text-slate-400">
            No features match your search.
          </div>
        ) : (
          getFilteredGroups().map((group) => {
            const GroupIcon = group.icon
            const originalGroup = FEATURE_GROUPS.find(g => g.id === group.id)
            const groupPaths = originalGroup?.items.map(item => item.path) || []
            const enabledCount = groupPaths.filter(path => enabledFeatures.includes(path)).length
            const allEnabled = enabledCount === groupPaths.length
            const someEnabled = enabledCount > 0 && enabledCount < groupPaths.length
            const isExpanded = expandedGroups.has(group.id)
            const orderedItems = searchQuery ? group.items : getOrderedItems(group.id)
            const isDraggingGroup = draggedGroup === group.id

            return (
              <div
                key={group.id}
                draggable={!searchQuery}
                onDragStart={(e) => !searchQuery && handleGroupDragStart(e, group.id)}
                onDragOver={handleDragOver}
                onDrop={(e) => !searchQuery && handleGroupDrop(e, group.id)}
                onDragEnd={handleGroupDragEnd}
                className={`border border-slate-200 dark:border-slate-700 rounded-lg overflow-hidden ${
                  isDraggingGroup ? 'opacity-50 ring-2 ring-indigo-500' : ''
                }`}
              >
                {/* Group header */}
                <div className="flex items-center justify-between px-4 py-3 bg-slate-50 dark:bg-slate-800/50">
                  <div className="flex items-center gap-3 flex-1">
                    {!searchQuery && (
                      <GripVertical className="w-4 h-4 text-slate-300 dark:text-slate-600 cursor-move" />
                    )}
                    <button
                      onClick={() => handleExpandToggle(group.id)}
                      className="flex items-center gap-3 flex-1 text-left"
                    >
                      <ChevronRight className={`w-4 h-4 text-slate-400 transition-transform ${isExpanded ? 'rotate-90' : ''}`} />
                      <GroupIcon className="w-5 h-5 text-slate-600 dark:text-slate-400" />
                      <span className="font-medium text-slate-900 dark:text-slate-100">{group.label}</span>
                      <span className="text-sm text-slate-500 dark:text-slate-400">
                        ({enabledCount}/{groupPaths.length})
                      </span>
                    </button>
                  </div>
                  <button
                    onClick={() => handleToggleGroup(group.id)}
                    className={`p-1 rounded transition-colors ${
                      allEnabled
                        ? 'text-indigo-600 dark:text-indigo-400 hover:bg-indigo-100 dark:hover:bg-indigo-900/30'
                        : 'text-slate-400 hover:bg-slate-200 dark:hover:bg-slate-700'
                    }`}
                    title={allEnabled ? 'Disable all in group' : 'Enable all in group'}
                  >
                    {allEnabled ? (
                      <CheckSquare className="w-5 h-5" />
                    ) : someEnabled ? (
                      <MinusSquare className="w-5 h-5" />
                    ) : (
                      <Square className="w-5 h-5" />
                    )}
                  </button>
                </div>

                {/* Group items */}
                {isExpanded && (
                  <div className="divide-y divide-slate-100 dark:divide-slate-800">
                    {orderedItems.map((item, index) => {
                      const ItemIcon = item.icon
                      const isEnabled = enabledFeatures.includes(item.path)
                      const isDragging = draggedItem?.groupId === group.id && draggedItem?.index === index
                      const isEditingThisLabel = editingLabel === item.path
                      const displayLabel = getDisplayLabel(item.path, item.label)
                      const hasCustomLabel = featureLabels[item.path] !== undefined

                      return (
                        <div
                          key={item.path}
                          draggable={!searchQuery && !isEditingThisLabel}
                          onDragStart={(e) => !searchQuery && handleDragStart(e, group.id, index)}
                          onDragOver={handleDragOver}
                          onDrop={(e) => !searchQuery && handleDrop(e, group.id, index)}
                          onDragEnd={handleDragEnd}
                          className={`flex items-center gap-3 px-4 py-2.5 transition-colors ${
                            isDragging ? 'opacity-50 bg-indigo-50 dark:bg-indigo-900/20' : 'hover:bg-slate-50 dark:hover:bg-slate-800/30'
                          } ${!searchQuery && !isEditingThisLabel ? 'cursor-move' : ''}`}
                        >
                          {!searchQuery && (
                            <GripVertical className="w-4 h-4 text-slate-300 dark:text-slate-600" />
                          )}
                          <button
                            onClick={() => handleToggleFeature(item.path)}
                            className={`p-0.5 rounded transition-colors ${
                              isEnabled
                                ? 'text-indigo-600 dark:text-indigo-400'
                                : 'text-slate-300 dark:text-slate-600 hover:text-slate-400 dark:hover:text-slate-500'
                            }`}
                          >
                            {isEnabled ? <CheckSquare className="w-5 h-5" /> : <Square className="w-5 h-5" />}
                          </button>
                          <ItemIcon className={`w-4 h-4 ${isEnabled ? 'text-slate-600 dark:text-slate-400' : 'text-slate-300 dark:text-slate-600'}`} />

                          {/* Editable label */}
                          {isEditingThisLabel ? (
                            <input
                              type="text"
                              value={editLabelValue}
                              onChange={(e) => setEditLabelValue(e.target.value)}
                              onBlur={() => handleLabelSave(item.path)}
                              onKeyDown={(e) => {
                                if (e.key === 'Enter') handleLabelSave(item.path)
                                if (e.key === 'Escape') setEditingLabel(null)
                              }}
                              autoFocus
                              className="flex-1 px-2 py-0.5 text-sm rounded border border-indigo-300 dark:border-indigo-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
                            />
                          ) : (
                            <span
                              onDoubleClick={() => handleLabelEdit(item.path)}
                              className={`flex-1 cursor-text ${isEnabled ? 'text-slate-900 dark:text-slate-100' : 'text-slate-400 dark:text-slate-500'}`}
                              title="Double-click to edit label"
                            >
                              {displayLabel}
                              {hasCustomLabel && (
                                <span className="ml-1 text-xs text-indigo-500 dark:text-indigo-400">(custom)</span>
                              )}
                            </span>
                          )}

                          <code className={`text-xs font-mono ${isEnabled ? 'text-slate-500 dark:text-slate-400' : 'text-slate-300 dark:text-slate-600'}`}>
                            {item.path}
                          </code>
                        </div>
                      )
                    })}
                  </div>
                )}
              </div>
            )
          })
        )}
      </div>
    </div>
  )
}
