import { useEffect, useState, useCallback } from 'react'
import { fetchAPI, postAPI, putAPI, deleteAPI } from '../api/client'
import { useToast } from '../components/Toast'
import StatusBadge from '../components/StatusBadge'
import ConfirmModal from '../components/ConfirmModal'
import Loading from '../components/Loading'

/* -------------------------------------------------------------------------- */
/*  Shared types                                                              */
/* -------------------------------------------------------------------------- */

interface Indexer {
  id: number
  name: string
  implementation: string
  url: string
  enabled: boolean
  failure_count: number
}

interface DownloadClient {
  id: number
  name: string
  implementation: string
  url: string
  api_key?: string
  category?: string
  priority?: number
  enabled: boolean
}

interface QualityProfile {
  id: number
  name: string
  media_types: string[]
  cutoff_quality: string
  allowed_qualities: string[]
}

interface RootFolder {
  id: number
  path: string
  media_type: string
  free_space: number | null
}

interface Tag {
  id: number
  name: string
  color: string
}

interface TaskInfo {
  id: number
  name: string
  cron_expr: string
  enabled: boolean
  last_run_at: string | null
  next_run_at: string | null
}

interface NotificationChannel {
  id: number
  name: string
  type: 'webhook' | 'telegram'
  enabled: boolean
  config: Record<string, string>
  event_types: string[]
  created_at: string
}

const EVENT_TYPES = [
  { value: 'grab', label: 'Grab' },
  { value: 'import', label: 'Import' },
  { value: 'download_complete', label: 'Download Complete' },
  { value: 'download_failed', label: 'Download Failed' },
  { value: 'quality_upgrade', label: 'Quality Upgrade' },
  { value: 'safety_block', label: 'Safety Block' },
  { value: 'error', label: 'Error' },
  { value: 'info', label: 'Info' },
] as const

/* -------------------------------------------------------------------------- */
/* Toggle helper (accessible switch) */
/* -------------------------------------------------------------------------- */

function Toggle({ checked, onChange, label }: { checked: boolean; onChange: () => void; label: string }) {
  return (
    <button
      role="switch"
      aria-checked={checked}
      aria-label={label}
      onClick={onChange}
      className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-400 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-900 ${
        checked ? 'bg-indigo-500' : 'bg-gray-700'
      }`}
    >
      <span className={`inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform ${checked ? 'translate-x-4' : 'translate-x-1'}`} />
    </button>
  )
}

/* -------------------------------------------------------------------------- */
/* Section wrapper */
/* -------------------------------------------------------------------------- */

function Section({ title, loading, error, onRetry, children }: {
  title: string
  loading: boolean
  error: string | null
  onRetry: () => void
  children: React.ReactNode
}) {
  return (
    <div className="bg-gray-900 border border-gray-800 rounded-lg p-6">
      <h3 className="text-xl font-semibold mb-4 text-gray-100">{title}</h3>
      {loading ? (
        <Loading />
      ) : error ? (
        <div className="bg-red-900/30 border border-red-800 rounded-lg p-4">
          <p className="text-red-400 text-sm">{error}</p>
          <button onClick={onRetry} className="text-red-300 text-xs underline mt-1">Retry</button>
        </div>
      ) : (
        children
      )}
    </div>
  )
}

function formatBytes(bytes: number | null): string {
  if (!bytes) return '—'
  const tb = bytes / 1e12
  if (tb >= 1) return `${tb.toFixed(1)} TB`
  const gb = bytes / 1e9
  return `${gb.toFixed(1)} GB`
}

/* -------------------------------------------------------------------------- */
/*  Metadata Section                                                          */
/* -------------------------------------------------------------------------- */

function MetadataSection() {
  const { showToast } = useToast()
  const [refreshing, setRefreshing] = useState(false)
  const [showConfirm, setShowConfirm] = useState(false)

  const handleRefreshAll = async () => {
    setShowConfirm(false)
    setRefreshing(true)
    try {
      await postAPI('/api/media/refresh-all', {})
      showToast('✓ Refreshing metadata for all monitored media...')
    } catch {
      showToast('Failed to trigger metadata refresh')
    } finally {
      setRefreshing(false)
    }
  }

  return (
    <Section title="Metadata" loading={false} error={null} onRetry={() => {}}>
      <p className="text-gray-400 text-sm mb-4">
        Re-fetch metadata from external providers (TMDB, etc.) for all monitored media items.
        This may take several minutes.
      </p>
      <button
        onClick={() => setShowConfirm(true)}
        disabled={refreshing}
        className="bg-gray-700 hover:bg-gray-600 disabled:opacity-50 px-4 py-2 rounded text-sm font-semibold min-h-[36px]"
      >
        {refreshing ? 'Refreshing...' : '↻ Refresh All Metadata'}
      </button>
      <ConfirmModal
        open={showConfirm}
        title="Refresh All Metadata"
        message="This will re-fetch metadata from external providers for all monitored media items. This operation may take several minutes to complete. Continue?"
        confirmLabel="Refresh All"
        onConfirm={handleRefreshAll}
        onCancel={() => setShowConfirm(false)}
      />
    </Section>
  )
}

/* -------------------------------------------------------------------------- */
/*  Settings Page                                                             */
/* -------------------------------------------------------------------------- */

export default function Settings() {
  return (
    <div>
      <h2 className="text-2xl font-semibold mb-6 text-gray-100">Settings</h2>
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        <NotificationsSection />
        <IndexersSection />
        <DownloadClientsSection />
        <QualityProfilesSection />
        <RootFoldersSection />
        <TagsSection />
        <TasksSection />
        <MetadataSection />
      </div>
    </div>
  )
}

/* -------------------------------------------------------------------------- */
/*  Notifications Section                                                     */
/* -------------------------------------------------------------------------- */

function NotificationsSection() {
  const { showToast } = useToast()
  const [items, setItems] = useState<NotificationChannel[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [testing, setTesting] = useState<number | null>(null)
  const [showAdd, setShowAdd] = useState(false)
  const [addForm, setAddForm] = useState({
    name: '',
    type: 'webhook' as 'webhook' | 'telegram',
    url: '',
    bot_token: '',
    chat_id: '',
    event_types: ['grab'] as string[],
  })
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editForm, setEditForm] = useState({
    name: '',
    config: {} as Record<string, string>,
    event_types: [] as string[],
  })

  const fetch_ = useCallback(() => {
    setLoading(true); setError(null)
    fetchAPI<NotificationChannel[]>('/api/notifications/channels')
      .then(d => setItems(d ?? []))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false))
  }, [])

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

  const testItem = async (id: number) => {
    setTesting(id)
    try {
      const res = await postAPI<{ success: boolean; error?: string }>(`/api/notifications/channels/${id}/test`, {})
      showToast(res.success ? 'Notification sent' : `Test failed: ${res.error ?? 'unknown'}`)
    } catch { showToast('Test failed') }
    setTesting(null)
  }

  const addItem = async () => {
    try {
      const body: Record<string, unknown> = {
        name: addForm.name,
        type: addForm.type,
        event_types: addForm.event_types,
      }
      if (addForm.type === 'webhook') {
        body.config = { url: addForm.url }
      } else {
        body.config = { bot_token: addForm.bot_token, chat_id: addForm.chat_id }
      }
      await postAPI('/api/notifications/channels', body)
      setShowAdd(false)
      setAddForm({
        name: '',
        type: 'webhook',
        url: '',
        bot_token: '',
        chat_id: '',
        event_types: ['grab'],
      })
      fetch_()
    } catch { showToast('Failed to add notification channel') }
  }

  const deleteItem = async (id: number) => {
    try { await deleteAPI(`/api/notifications/channels/${id}`); fetch_() } catch { showToast('Failed to delete') }
  }

  const toggleEnabled = async (item: NotificationChannel) => {
    try {
      await putAPI(`/api/notifications/channels/${item.id}`, { enabled: !item.enabled })
      fetch_()
    } catch { showToast('Failed to toggle') }
  }

  const toggleEventType = (eventType: string) => {
    setAddForm(prev => ({
      ...prev,
      event_types: prev.event_types.includes(eventType)
        ? prev.event_types.filter(t => t !== eventType)
        : [...prev.event_types, eventType],
    }))
  }

  const toggleEditEventType = (eventType: string) => {
    setEditForm(prev => ({
      ...prev,
      event_types: prev.event_types.includes(eventType)
        ? prev.event_types.filter(t => t !== eventType)
        : [...prev.event_types, eventType],
    }))
  }

  const startEdit = (item: NotificationChannel) => {
    if (showAdd) return
    setEditingId(item.id)
    setEditForm({
      name: item.name,
      config: { ...item.config },
      event_types: [...item.event_types],
    })
  }

  const saveEdit = async (item: NotificationChannel) => {
    try {
      const body: Record<string, unknown> = { name: editForm.name, event_types: editForm.event_types }
      if (item.type === 'webhook') {
        body.config = { url: editForm.config['url'] ?? '' }
      } else {
        body.config = { bot_token: editForm.config['bot_token'] ?? '', chat_id: editForm.config['chat_id'] ?? '' }
      }
      await putAPI(`/api/notifications/channels/${item.id}`, body)
      setEditingId(null)
      fetch_()
    } catch { showToast('Failed to save') }
  }

  const typeBadgeColor = (type: string) =>
    type === 'webhook' ? 'bg-blue-900/40 text-blue-300' : 'bg-cyan-900/40 text-cyan-300'

  return (
    <Section title="Notifications" loading={loading} error={error} onRetry={fetch_}>
      {items.length === 0 ? (
        <p className="text-gray-500 text-sm">No notification channels configured. Add one to receive alerts.</p>
      ) : (
        <div className="space-y-3 mb-4">
          {items.map(item => (
            editingId === item.id ? (
              <div key={item.id} className="border-b border-gray-800/50 pb-3 space-y-2">
                <input placeholder="Name" value={editForm.name} onChange={e => setEditForm({ ...editForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                {item.type === 'webhook' ? (
                  <input placeholder="Webhook URL" value={editForm.config['url'] ?? ''} onChange={e => setEditForm({ ...editForm, config: { ...editForm.config, url: e.target.value } })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                ) : (
                  <>
                    <input placeholder="Bot Token" type="password" value={editForm.config['bot_token'] ?? ''} onChange={e => setEditForm({ ...editForm, config: { ...editForm.config, bot_token: e.target.value } })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                    <input placeholder="Chat ID" value={editForm.config['chat_id'] ?? ''} onChange={e => setEditForm({ ...editForm, config: { ...editForm.config, chat_id: e.target.value } })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                  </>
                )}
                <div className="grid grid-cols-2 gap-x-4 gap-y-1">
                  {EVENT_TYPES.map(et => (
                    <label key={et.value} className="flex items-center gap-2 text-sm text-gray-300 py-0.5 cursor-pointer">
                      <input
                        type="checkbox"
                        checked={editForm.event_types.includes(et.value)}
                        onChange={() => toggleEditEventType(et.value)}
                        className="rounded border-gray-600 bg-gray-800 text-indigo-500 focus:ring-indigo-500"
                      />
                      {et.label}
                    </label>
                  ))}
                </div>
                <div className="flex items-center gap-2">
                  <button onClick={() => saveEdit(item)} className="bg-indigo-500 hover:bg-indigo-400 px-3 py-1.5 rounded text-sm min-h-[36px]">Save</button>
                  <button onClick={() => setEditingId(null)} className="bg-gray-700 hover:bg-gray-600 px-3 py-1.5 rounded text-sm min-h-[36px]">Cancel</button>
                  <button onClick={() => testItem(item.id)} disabled={testing === item.id} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">
                    {testing === item.id ? 'Testing...' : 'Test'}
                  </button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            ) : (
              <div key={item.id} className="border-b border-gray-800/50 pb-3">
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-3 min-w-0">
<Toggle checked={item.enabled} onChange={() => toggleEnabled(item)} label={`${item.name}: ${item.enabled ? 'disable' : 'enable'}`} />
                    <div className="min-w-0">
                      <div className="flex items-center gap-2">
                        <p className="text-sm text-gray-100 truncate">{item.name}</p>
                        <span className={`text-xs px-1.5 py-0.5 rounded ${typeBadgeColor(item.type)}`}>{item.type}</span>
                      </div>
                      <p className="text-xs text-gray-500 mt-0.5">
                        {item.type === 'webhook'
                          ? (item.config['url'] ?? '—')
                          : `chat: ${item.config['chat_id'] ?? '—'}`}
                      </p>
                    </div>
                  </div>
                  <div className="flex items-center gap-2">
                    <button onClick={() => startEdit(item)} disabled={showAdd} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">Edit</button>
                    <button onClick={() => testItem(item.id)} disabled={testing === item.id} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">
                      {testing === item.id ? 'Testing...' : 'Test'}
                    </button>
                    <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                  </div>
                </div>
                {item.event_types.length > 0 && (
                  <div className="flex flex-wrap gap-1 mt-2 ml-5">
                    {item.event_types.map(et => (
                      <span key={et} className="text-xs bg-gray-800 text-gray-400 px-1.5 py-0.5 rounded">{et.replace(/_/g, ' ')}</span>
                    ))}
                  </div>
                )}
              </div>
            )
          ))}
        </div>
      )}
      {showAdd ? (
        <div className="space-y-2 border-t border-gray-800 pt-4">
          <input placeholder="Name (3-50 chars)" value={addForm.name} onChange={e => setAddForm({ ...addForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <select value={addForm.type} onChange={e => setAddForm({ ...addForm, type: e.target.value as 'webhook' | 'telegram' })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100">
            <option value="webhook">Webhook</option>
            <option value="telegram">Telegram</option>
          </select>
          {addForm.type === 'webhook' ? (
            <input placeholder="Webhook URL" value={addForm.url} onChange={e => setAddForm({ ...addForm, url: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          ) : (
            <>
              <input placeholder="Bot Token" type="password" value={addForm.bot_token} onChange={e => setAddForm({ ...addForm, bot_token: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
              <input placeholder="Chat ID" value={addForm.chat_id} onChange={e => setAddForm({ ...addForm, chat_id: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
            </>
          )}
          <div className="grid grid-cols-2 gap-x-4 gap-y-1">
            {EVENT_TYPES.map(et => (
              <label key={et.value} className="flex items-center gap-2 text-sm text-gray-300 py-0.5 cursor-pointer">
                <input
                  type="checkbox"
                  checked={addForm.event_types.includes(et.value)}
                  onChange={() => toggleEventType(et.value)}
                  className="rounded border-gray-600 bg-gray-800 text-indigo-500 focus:ring-indigo-500"
                />
                {et.label}
              </label>
            ))}
          </div>
          <div className="flex gap-2">
            <button onClick={addItem} className="bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-sm font-semibold min-h-[36px]">Add</button>
            <button onClick={() => setShowAdd(false)} className="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded text-sm min-h-[36px]">Cancel</button>
          </div>
        </div>
      ) : (
        <button onClick={() => { setShowAdd(true); setEditingId(null) }} className="text-sm text-indigo-400 hover:text-indigo-300">+ Add Channel</button>
      )}
    </Section>
  )
}

/* -------------------------------------------------------------------------- */
/*  Indexers Section                                                          */
/* -------------------------------------------------------------------------- */

interface CardigannSettingsField {
  name: string
  type: string
  label: string
}

interface CardigannValidation {
  valid: boolean
  definition?: {
    site: string
    name: string
    settings: CardigannSettingsField[]
    has_login: boolean
  }
  error?: string
  warnings?: string[]
}

const implBadgeColor = (impl: string) => {
  switch (impl) {
    case 'torznab': return 'bg-green-900/40 text-green-300'
    case 'newznab': return 'bg-blue-900/40 text-blue-300'
    case 'cardigann': return 'bg-amber-900/40 text-amber-300'
    default: return 'bg-gray-800 text-gray-400'
  }
}

function IndexersSection() {
  const { showToast } = useToast()
  const [items, setItems] = useState<Indexer[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [testing, setTesting] = useState<number | null>(null)
  const [showAdd, setShowAdd] = useState(false)
  const [addForm, setAddForm] = useState({ name: '', implementation: 'newznab', url: '', api_key: '' })

  // Cardigann-specific state
  const [yamlInput, setYamlInput] = useState('')
  const [yamlValidation, setYamlValidation] = useState<CardigannValidation | null>(null)
  const [validating, setValidating] = useState(false)
  const [cardigannConfig, setCardigannConfig] = useState<Record<string, string>>({})
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editForm, setEditForm] = useState({ name: '', url: '', api_key: '', enabled: true })

  const fetch_ = useCallback(() => {
    setLoading(true); setError(null)
    fetchAPI<Indexer[]>('/api/indexers')
      .then(d => setItems(d ?? []))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false))
  }, [])

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

  const toggleEnabled = async (item: Indexer) => {
    try {
      await putAPI(`/api/indexers/${item.id}`, { enabled: !item.enabled })
      fetch_()
    } catch { showToast('Failed to toggle') }
  }

  const startEdit = (item: Indexer) => {
    if (showAdd) return
    setEditingId(item.id)
    setEditForm({ name: item.name, url: item.url, api_key: '', enabled: item.enabled })
  }

  const saveEdit = async (id: number) => {
    try {
      const body: Record<string, unknown> = { name: editForm.name, url: editForm.url, enabled: editForm.enabled }
      if (editForm.api_key) body.api_key = editForm.api_key
      await putAPI(`/api/indexers/${id}`, body)
      setEditingId(null)
      fetch_()
    } catch { showToast('Failed to save') }
  }

  const testItem = async (id: number) => {
    setTesting(id)
    try {
      const res = await postAPI<{ success: boolean; error?: string }>(`/api/indexers/${id}/test`, {})
      showToast(res.success ? 'Connected' : `Connection failed: ${res.error ?? 'unknown'}`)
    } catch { showToast('Connection failed') }
    setTesting(null)
  }

  const validateYaml = async () => {
    if (!yamlInput.trim()) return
    setValidating(true)
    try {
      const res = await postAPI<CardigannValidation>('/api/indexers/validate-cardigann', { yaml: yamlInput })
      setYamlValidation(res)
      if (res.valid && res.definition) {
        // Pre-populate name from definition
        setAddForm(prev => ({ ...prev, name: prev.name || res.definition!.name }))
      }
    } catch {
      setYamlValidation({ valid: false, error: 'Validation request failed' })
    }
    setValidating(false)
  }

  const addItem = async () => {
    try {
      if (addForm.implementation === 'cardigann') {
        if (!yamlValidation?.valid) {
          showToast('Please validate the YAML definition first')
          return
        }
        await postAPI('/api/indexers', {
          name: addForm.name || yamlValidation.definition?.name || '',
          implementation: 'cardigann',
          url: '',
          settings: {
            yaml: yamlInput,
            config: cardigannConfig,
          },
        })
      } else {
        await postAPI('/api/indexers', addForm)
      }
      setShowAdd(false)
      setAddForm({ name: '', implementation: 'newznab', url: '', api_key: '' })
      setYamlInput('')
      setYamlValidation(null)
      setCardigannConfig({})
      fetch_()
    } catch { showToast('Failed to add indexer') }
  }

  const deleteItem = async (id: number) => {
    try { await deleteAPI(`/api/indexers/${id}`); fetch_() } catch { showToast('Failed to delete') }
  }

  const resetAddForm = () => {
    setShowAdd(false)
    setAddForm({ name: '', implementation: 'newznab', url: '', api_key: '' })
    setYamlInput('')
    setYamlValidation(null)
    setCardigannConfig({})
  }

  return (
    <Section title="Indexers" loading={loading} error={error} onRetry={fetch_}>
      {items.length === 0 ? (
        <p className="text-gray-500 text-sm">No indexers configured. Add one to start searching.</p>
      ) : (
        <div className="space-y-2 mb-4">
          {items.map(item => (
            editingId === item.id ? (
              <div key={item.id} className="py-2 border-b border-gray-800/50 space-y-2">
                <input placeholder="Name" value={editForm.name} onChange={e => setEditForm({ ...editForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
{item.implementation !== 'cardigann' && (
            <>
            <input placeholder="URL" value={editForm.url} onChange={e => setEditForm({ ...editForm, url: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
            <input placeholder="API Key (leave empty to keep current)" type="password" value={editForm.api_key} onChange={e => setEditForm({ ...editForm, api_key: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
            </>
          )}
          <div className="flex items-center gap-2">
            <Toggle checked={editForm.enabled} onChange={() => setEditForm({ ...editForm, enabled: !editForm.enabled })} label="Indexer enabled" />
            <span className="text-xs text-gray-400">{editForm.enabled ? 'Enabled' : 'Disabled'}</span>
          </div>
          <div className="flex items-center gap-2">
            <button onClick={() => saveEdit(item.id)} className="bg-indigo-500 hover:bg-indigo-400 px-3 py-1.5 rounded text-sm min-h-[36px]">Save</button>
                  <button onClick={() => setEditingId(null)} className="bg-gray-700 hover:bg-gray-600 px-3 py-1.5 rounded text-sm min-h-[36px]">Cancel</button>
                  <button onClick={() => testItem(item.id)} disabled={testing === item.id} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">
                    {testing === item.id ? 'Testing...' : 'Test'}
                  </button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            ) : (
              <div key={item.id} className="flex items-center justify-between py-2 border-b border-gray-800/50">
                <div className="flex items-center gap-3 min-w-0">
<Toggle checked={item.enabled} onChange={() => toggleEnabled(item)} label={`${item.name}: ${item.enabled ? 'disable' : 'enable'}`} />
                <div className="min-w-0">
                  <div className="flex items-center gap-2">
                    <p className="text-sm text-gray-100 truncate">{item.name}</p>
                      <span className={`text-xs px-1.5 py-0.5 rounded ${implBadgeColor(item.implementation)}`}>{item.implementation}</span>
                    </div>
                    <p className="text-xs text-gray-500 mt-0.5">
                      {item.implementation === 'cardigann' ? 'YAML definition' : item.url}
                    </p>
                  </div>
                </div>
                <div className="flex items-center gap-2">
                  <button onClick={() => startEdit(item)} disabled={showAdd} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">Edit</button>
                  <button onClick={() => testItem(item.id)} disabled={testing === item.id} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">
                    {testing === item.id ? 'Testing...' : 'Test'}
                  </button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            )
          ))}
        </div>
      )}
      {showAdd ? (
        <div className="space-y-2 border-t border-gray-800 pt-4">
          <input placeholder="Name" value={addForm.name} onChange={e => setAddForm({ ...addForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <select value={addForm.implementation} onChange={e => {
            setAddForm({ ...addForm, implementation: e.target.value })
            setYamlInput('')
            setYamlValidation(null)
            setCardigannConfig({})
          }} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100">
            <option value="newznab">Newznab</option>
            <option value="torznab">Torznab</option>
            <option value="cardigann">Cardigann</option>
          </select>

          {addForm.implementation === 'cardigann' ? (
            <>
              <div>
                <label className="block text-xs text-gray-400 mb-1">YAML Definition</label>
                <textarea
                  value={yamlInput}
                  onChange={e => { setYamlInput(e.target.value); setYamlValidation(null) }}
                  placeholder="Paste Cardigann YAML definition here..."
                  rows={10}
                  className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100 font-mono min-h-[200px] resize-y"
                />
              </div>
              <div className="flex items-center gap-2">
                <button
                  onClick={validateYaml}
                  disabled={validating || !yamlInput.trim()}
                  className="bg-gray-700 hover:bg-gray-600 px-3 py-1.5 rounded text-sm disabled:opacity-50 min-h-[36px]"
                >
                  {validating ? 'Validating...' : 'Validate'}
                </button>
                {yamlValidation && (
                  yamlValidation.valid ? (
                    <span className="text-green-400 text-xs">✓ Valid</span>
                  ) : (
                    <span className="text-red-400 text-xs">✗ {yamlValidation.error}</span>
                  )
                )}
              </div>

              {yamlValidation?.valid && yamlValidation.definition && (
                <div className="bg-gray-800/50 border border-gray-700 rounded p-3 space-y-2">
                  <div className="flex items-center gap-2">
                    <span className="text-green-400 text-xs font-semibold">Definition:</span>
                    <span className="text-sm text-gray-100">{yamlValidation.definition.name}</span>
                    <span className="text-xs text-gray-500">({yamlValidation.definition.site})</span>
                    {yamlValidation.definition.has_login && (
                      <span className="text-xs bg-amber-900/40 text-amber-300 px-1.5 py-0.5 rounded">has login</span>
                    )}
                  </div>

                  {yamlValidation.definition.settings.length > 0 && (
                    <div className="space-y-1.5">
                      <p className="text-xs text-gray-400">Configuration:</p>
                      {yamlValidation.definition.settings.map(field => (
                        <div key={field.name}>
                          <label className="block text-xs text-gray-500 mb-0.5">
                            {field.label || field.name}
                          </label>
                          <input
                            type={field.type === 'password' ? 'password' : 'text'}
                            placeholder={field.label || field.name}
                            value={cardigannConfig[field.name] ?? ''}
                            onChange={e => setCardigannConfig({ ...cardigannConfig, [field.name]: e.target.value })}
                            className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-1.5 text-sm text-gray-100"
                          />
                        </div>
                      ))}
                    </div>
                  )}

                  {yamlValidation.warnings && yamlValidation.warnings.length > 0 && (
                    <div className="space-y-0.5">
                      {yamlValidation.warnings.map((w, i) => (
                        <p key={i} className="text-yellow-400 text-xs">⚠ {w}</p>
                      ))}
                    </div>
                  )}
                </div>
              )}
            </>
          ) : (
            <>
              <input placeholder="URL" value={addForm.url} onChange={e => setAddForm({ ...addForm, url: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
              <input placeholder="API Key" value={addForm.api_key} onChange={e => setAddForm({ ...addForm, api_key: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
            </>
          )}

          <div className="flex gap-2">
            <button onClick={addItem} className="bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-sm font-semibold min-h-[36px]">Add</button>
            <button onClick={resetAddForm} className="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded text-sm min-h-[36px]">Cancel</button>
          </div>
        </div>
      ) : (
        <button onClick={() => { setShowAdd(true); setEditingId(null) }} className="text-sm text-indigo-400 hover:text-indigo-300">+ Add Indexer</button>
      )}
    </Section>
  )
}

/* -------------------------------------------------------------------------- */
/*  Download Clients Section                                                  */
/* -------------------------------------------------------------------------- */

function DownloadClientsSection() {
  const { showToast } = useToast()
  const [items, setItems] = useState<DownloadClient[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [testing, setTesting] = useState<number | null>(null)
  const [showAdd, setShowAdd] = useState(false)
  const [addForm, setAddForm] = useState({ name: '', implementation: 'sabnzbd', url: '', api_key: '' })
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editForm, setEditForm] = useState({ name: '', url: '', api_key: '', category: '', priority: 0, enabled: true })

  const fetch_ = useCallback(() => {
    setLoading(true); setError(null)
    fetchAPI<DownloadClient[]>('/api/download-clients')
      .then(d => setItems(d ?? []))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false))
  }, [])

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

  const toggleEnabled = async (item: DownloadClient) => {
    try {
      await putAPI(`/api/download-clients/${item.id}`, { enabled: !item.enabled })
      fetch_()
    } catch { showToast('Failed to toggle') }
  }

  const startEdit = (item: DownloadClient) => {
    if (showAdd) return
    setEditingId(item.id)
    setEditForm({ name: item.name, url: item.url, api_key: '', category: item.category ?? '', priority: item.priority ?? 0, enabled: item.enabled })
  }

  const saveEdit = async (id: number) => {
    try {
      const body: Record<string, unknown> = { name: editForm.name, url: editForm.url, enabled: editForm.enabled, category: editForm.category, priority: editForm.priority }
      if (editForm.api_key) body.api_key = editForm.api_key
      await putAPI(`/api/download-clients/${id}`, body)
      setEditingId(null)
      fetch_()
    } catch { showToast('Failed to save') }
  }

  const testItem = async (id: number) => {
    setTesting(id)
    try {
      const res = await postAPI<{ success?: boolean; error?: string }>(`/api/download-clients/${id}/test`, {})
      showToast(res.error ? `Connection failed: ${res.error}` : 'Connected')
    } catch { showToast('Connection failed') }
    setTesting(null)
  }

  const addItem = async () => {
    try {
      await postAPI('/api/download-clients', addForm)
      setShowAdd(false)
      setAddForm({ name: '', implementation: 'sabnzbd', url: '', api_key: '' })
      fetch_()
    } catch { showToast('Failed to add client') }
  }

  const deleteItem = async (id: number) => {
    try { await deleteAPI(`/api/download-clients/${id}`); fetch_() } catch { showToast('Failed to delete') }
  }

  return (
    <Section title="Download Clients" loading={loading} error={error} onRetry={fetch_}>
      {items.length === 0 ? (
        <p className="text-gray-500 text-sm">No download clients configured.</p>
      ) : (
        <div className="space-y-2 mb-4">
          {items.map(item => (
            editingId === item.id ? (
              <div key={item.id} className="py-2 border-b border-gray-800/50 space-y-2">
                <input placeholder="Name" value={editForm.name} onChange={e => setEditForm({ ...editForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <input placeholder="URL" value={editForm.url} onChange={e => setEditForm({ ...editForm, url: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <input placeholder="API Key (leave empty to keep current)" type="password" value={editForm.api_key} onChange={e => setEditForm({ ...editForm, api_key: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <input placeholder="Category" value={editForm.category} onChange={e => setEditForm({ ...editForm, category: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
<input placeholder="Priority" type="number" value={editForm.priority} onChange={e => setEditForm({ ...editForm, priority: parseInt(e.target.value) || 0 })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <div className="flex items-center gap-2">
            <Toggle checked={editForm.enabled} onChange={() => setEditForm({ ...editForm, enabled: !editForm.enabled })} label="Download client enabled" />
            <span className="text-xs text-gray-400">{editForm.enabled ? 'Enabled' : 'Disabled'}</span>
          </div>
          <div className="flex items-center gap-2">
            <button onClick={() => saveEdit(item.id)} className="bg-indigo-500 hover:bg-indigo-400 px-3 py-1.5 rounded text-sm min-h-[36px]">Save</button>
            <button onClick={() => setEditingId(null)} className="bg-gray-700 hover:bg-gray-600 px-3 py-1.5 rounded text-sm min-h-[36px]">Cancel</button>
                  <button onClick={() => testItem(item.id)} disabled={testing === item.id} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">
                    {testing === item.id ? 'Testing...' : 'Test'}
                  </button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            ) : (
              <div key={item.id} className="flex items-center justify-between py-2 border-b border-gray-800/50">
<div className="flex items-center gap-3 min-w-0">
          <Toggle checked={item.enabled} onChange={() => toggleEnabled(item)} label={`${item.name}: ${item.enabled ? 'disable' : 'enable'}`} />
          <div className="min-w-0">
            <p className="text-sm text-gray-100 truncate">{item.name}</p>
                    <p className="text-xs text-gray-500">{item.implementation} • {item.url}</p>
                  </div>
                </div>
                <div className="flex items-center gap-2">
                  <button onClick={() => startEdit(item)} disabled={showAdd} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">Edit</button>
                  <button onClick={() => testItem(item.id)} disabled={testing === item.id} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">
                    {testing === item.id ? 'Testing...' : 'Test'}
                  </button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            )
          ))}
        </div>
      )}
      {showAdd ? (
        <div className="space-y-2 border-t border-gray-800 pt-4">
          <input placeholder="Name" value={addForm.name} onChange={e => setAddForm({ ...addForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <select value={addForm.implementation} onChange={e => setAddForm({ ...addForm, implementation: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100">
            <option value="sabnzbd">SABnzbd</option>
            <option value="qbittorrent">qBittorrent</option>
          </select>
          <input placeholder="URL" value={addForm.url} onChange={e => setAddForm({ ...addForm, url: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <input placeholder="API Key" value={addForm.api_key} onChange={e => setAddForm({ ...addForm, api_key: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <div className="flex gap-2">
            <button onClick={addItem} className="bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-sm font-semibold min-h-[36px]">Add</button>
            <button onClick={() => setShowAdd(false)} className="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded text-sm min-h-[36px]">Cancel</button>
          </div>
        </div>
      ) : (
        <button onClick={() => { setShowAdd(true); setEditingId(null) }} className="text-sm text-indigo-400 hover:text-indigo-300">+ Add Client</button>
      )}
    </Section>
  )
}

/* -------------------------------------------------------------------------- */
/*  Quality Profiles Section                                                  */
/* -------------------------------------------------------------------------- */

function QualityProfilesSection() {
  const { showToast } = useToast()
  const [items, setItems] = useState<QualityProfile[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [showAdd, setShowAdd] = useState(false)
  const [addForm, setAddForm] = useState({ name: '', media_types: 'movie', cutoff_quality: '', allowed_qualities: '' })
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editForm, setEditForm] = useState({ name: '', cutoff_quality: '', allowed_qualities: '' })

  const fetch_ = useCallback(() => {
    setLoading(true); setError(null)
    fetchAPI<QualityProfile[]>('/api/quality-profiles')
      .then(d => setItems(d ?? []))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false))
  }, [])

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

  const startEdit = (item: QualityProfile) => {
    if (showAdd) return
    setEditingId(item.id)
    setEditForm({ name: item.name, cutoff_quality: item.cutoff_quality, allowed_qualities: item.allowed_qualities.join(', ') })
  }

  const saveEdit = async (id: number) => {
    try {
      await putAPI(`/api/quality-profiles/${id}`, {
        name: editForm.name,
        cutoff_quality: editForm.cutoff_quality,
        allowed_qualities: editForm.allowed_qualities.split(',').map(s => s.trim()).filter(Boolean),
      })
      setEditingId(null)
      fetch_()
    } catch { showToast('Failed to save') }
  }

  const addItem = async () => {
    try {
      await postAPI('/api/quality-profiles', {
        name: addForm.name,
        media_types: addForm.media_types.split(',').map(s => s.trim()),
        cutoff_quality: addForm.cutoff_quality,
        allowed_qualities: addForm.allowed_qualities.split(',').map(s => s.trim()),
      })
      setShowAdd(false)
      setAddForm({ name: '', media_types: 'movie', cutoff_quality: '', allowed_qualities: '' })
      fetch_()
    } catch { showToast('Failed to add profile') }
  }

  const deleteItem = async (id: number) => {
    try { await deleteAPI(`/api/quality-profiles/${id}`); fetch_() } catch { showToast('Failed to delete') }
  }

  return (
    <Section title="Quality Profiles" loading={loading} error={error} onRetry={fetch_}>
      {items.length === 0 ? (
        <p className="text-gray-500 text-sm">No quality profiles configured.</p>
      ) : (
        <div className="space-y-2 mb-4">
          {items.map(item => (
            editingId === item.id ? (
              <div key={item.id} className="py-2 border-b border-gray-800/50 space-y-2">
                <input placeholder="Name" value={editForm.name} onChange={e => setEditForm({ ...editForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <input placeholder="Cutoff quality" value={editForm.cutoff_quality} onChange={e => setEditForm({ ...editForm, cutoff_quality: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <input placeholder="Allowed qualities (comma-sep)" value={editForm.allowed_qualities} onChange={e => setEditForm({ ...editForm, allowed_qualities: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <div className="flex gap-1">
                  {item.media_types.map(mt => (
                    <span key={mt} className="text-xs bg-gray-800 text-gray-400 px-2 py-0.5 rounded">{mt}</span>
                  ))}
                  <span className="text-xs text-gray-500">(media types not editable)</span>
                </div>
                <div className="flex items-center gap-2">
                  <button onClick={() => saveEdit(item.id)} className="bg-indigo-500 hover:bg-indigo-400 px-3 py-1.5 rounded text-sm min-h-[36px]">Save</button>
                  <button onClick={() => setEditingId(null)} className="bg-gray-700 hover:bg-gray-600 px-3 py-1.5 rounded text-sm min-h-[36px]">Cancel</button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            ) : (
              <div key={item.id} className="flex items-center justify-between py-2 border-b border-gray-800/50">
                <div>
                  <p className="text-sm text-gray-100">{item.name}</p>
                  <div className="flex gap-1 mt-1">
                    {item.media_types.map(mt => (
                      <span key={mt} className="text-xs bg-gray-800 text-gray-400 px-2 py-0.5 rounded">{mt}</span>
                    ))}
                  </div>
                </div>
                <div className="flex items-center gap-2">
                  <button onClick={() => startEdit(item)} disabled={showAdd} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">Edit</button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            )
          ))}
        </div>
      )}
      {showAdd ? (
        <div className="space-y-2 border-t border-gray-800 pt-4">
          <input placeholder="Name" value={addForm.name} onChange={e => setAddForm({ ...addForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <input placeholder="Media types (comma-sep)" value={addForm.media_types} onChange={e => setAddForm({ ...addForm, media_types: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <input placeholder="Cutoff quality" value={addForm.cutoff_quality} onChange={e => setAddForm({ ...addForm, cutoff_quality: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <input placeholder="Allowed qualities (comma-sep)" value={addForm.allowed_qualities} onChange={e => setAddForm({ ...addForm, allowed_qualities: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <div className="flex gap-2">
            <button onClick={addItem} className="bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-sm font-semibold min-h-[36px]">Add</button>
            <button onClick={() => setShowAdd(false)} className="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded text-sm min-h-[36px]">Cancel</button>
          </div>
        </div>
      ) : (
        <button onClick={() => { setShowAdd(true); setEditingId(null) }} className="text-sm text-indigo-400 hover:text-indigo-300">+ Add Profile</button>
      )}
    </Section>
  )
}

/* -------------------------------------------------------------------------- */
/*  Root Folders Section                                                      */
/* -------------------------------------------------------------------------- */

function RootFoldersSection() {
  const { showToast } = useToast()
  const [items, setItems] = useState<RootFolder[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [showAdd, setShowAdd] = useState(false)
  const [addForm, setAddForm] = useState({ path: '', media_type: 'movie' })
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editForm, setEditForm] = useState({ path: '', media_type: 'movie' })

  const fetch_ = useCallback(() => {
    setLoading(true); setError(null)
    fetchAPI<RootFolder[]>('/api/root-folders')
      .then(d => setItems(d ?? []))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false))
  }, [])

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

  const startEdit = (item: RootFolder) => {
    if (showAdd) return
    setEditingId(item.id)
    setEditForm({ path: item.path, media_type: item.media_type })
  }

  const saveEdit = async (id: number) => {
    try {
      await deleteAPI(`/api/root-folders/${id}`)
      await postAPI('/api/root-folders', { path: editForm.path, media_type: editForm.media_type })
      setEditingId(null)
      fetch_()
    } catch { showToast('Failed to update root folder') }
  }

  const addItem = async () => {
    try {
      await postAPI('/api/root-folders', addForm)
      setShowAdd(false)
      setAddForm({ path: '', media_type: 'movie' })
      fetch_()
    } catch { showToast('Failed to add folder') }
  }

  const deleteItem = async (id: number) => {
    try { await deleteAPI(`/api/root-folders/${id}`); fetch_() } catch { showToast('Failed to delete') }
  }

  return (
    <Section title="Root Folders" loading={loading} error={error} onRetry={fetch_}>
      {items.length === 0 ? (
        <p className="text-gray-500 text-sm">No root folders configured.</p>
      ) : (
        <div className="space-y-2 mb-4">
          {items.map(item => (
            editingId === item.id ? (
              <div key={item.id} className="py-2 border-b border-gray-800/50 space-y-2">
                <input placeholder="Path (e.g. /data/movies)" value={editForm.path} onChange={e => setEditForm({ ...editForm, path: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <select value={editForm.media_type} onChange={e => setEditForm({ ...editForm, media_type: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100">
                  <option value="movie">Movie</option>
                  <option value="series">Series</option>
                  <option value="music">Music</option>
                  <option value="book">Book</option>
                </select>
                <p className="text-xs text-yellow-500">⚠ Saving will delete and re-create this folder entry</p>
                <div className="flex items-center gap-2">
                  <button onClick={() => saveEdit(item.id)} className="bg-indigo-500 hover:bg-indigo-400 px-3 py-1.5 rounded text-sm min-h-[36px]">Save</button>
                  <button onClick={() => setEditingId(null)} className="bg-gray-700 hover:bg-gray-600 px-3 py-1.5 rounded text-sm min-h-[36px]">Cancel</button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            ) : (
              <div key={item.id} className="flex items-center justify-between py-2 border-b border-gray-800/50">
                <div>
                  <p className="text-sm text-gray-100">{item.path}</p>
                  <p className="text-xs text-gray-500">{item.media_type} • {formatBytes(item.free_space)} free</p>
                </div>
                <div className="flex items-center gap-2">
                  <button onClick={() => startEdit(item)} disabled={showAdd} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">Edit</button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            )
          ))}
        </div>
      )}
      {showAdd ? (
        <div className="space-y-2 border-t border-gray-800 pt-4">
          <input placeholder="Path (e.g. /data/movies)" value={addForm.path} onChange={e => setAddForm({ ...addForm, path: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <select value={addForm.media_type} onChange={e => setAddForm({ ...addForm, media_type: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100">
            <option value="movie">Movie</option>
            <option value="series">Series</option>
            <option value="music">Music</option>
            <option value="book">Book</option>
          </select>
          <div className="flex gap-2">
            <button onClick={addItem} className="bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-sm font-semibold min-h-[36px]">Add</button>
            <button onClick={() => setShowAdd(false)} className="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded text-sm min-h-[36px]">Cancel</button>
          </div>
        </div>
      ) : (
        <button onClick={() => { setShowAdd(true); setEditingId(null) }} className="text-sm text-indigo-400 hover:text-indigo-300">+ Add Folder</button>
      )}
    </Section>
  )
}

/* -------------------------------------------------------------------------- */
/*  Tags Section                                                              */
/* -------------------------------------------------------------------------- */

function TagsSection() {
  const { showToast } = useToast()
  const [items, setItems] = useState<Tag[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [showAdd, setShowAdd] = useState(false)
  const [addForm, setAddForm] = useState({ name: '', color: '#6366f1' })
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editForm, setEditForm] = useState({ name: '', color: '#6366f1' })

  const fetch_ = useCallback(() => {
    setLoading(true); setError(null)
    fetchAPI<Tag[]>('/api/tags')
      .then(d => setItems(d ?? []))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false))
  }, [])

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

  const startEdit = (item: Tag) => {
    if (showAdd) return
    setEditingId(item.id)
    setEditForm({ name: item.name, color: item.color })
  }

  const saveEdit = async (id: number) => {
    try {
      await deleteAPI(`/api/tags/${id}`)
      await postAPI('/api/tags', { name: editForm.name, color: editForm.color })
      setEditingId(null)
      fetch_()
    } catch { showToast('Failed to update tag') }
  }

  const addItem = async () => {
    try {
      await postAPI('/api/tags', addForm)
      setShowAdd(false)
      setAddForm({ name: '', color: '#6366f1' })
      fetch_()
    } catch { showToast('Failed to add tag') }
  }

  const deleteItem = async (id: number) => {
    try { await deleteAPI(`/api/tags/${id}`); fetch_() } catch { showToast('Failed to delete') }
  }

  return (
    <Section title="Tags" loading={loading} error={error} onRetry={fetch_}>
      {items.length === 0 ? (
        <p className="text-gray-500 text-sm">No tags configured.</p>
      ) : (
        <div className="space-y-2 mb-4">
          {items.map(item => (
            editingId === item.id ? (
              <div key={item.id} className="py-2 border-b border-gray-800/50 space-y-2">
                <input placeholder="Name" value={editForm.name} onChange={e => setEditForm({ ...editForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                <div className="flex items-center gap-2">
                  <input type="color" value={editForm.color} onChange={e => setEditForm({ ...editForm, color: e.target.value })} className="h-8 w-8 rounded cursor-pointer" />
                  <input value={editForm.color} onChange={e => setEditForm({ ...editForm, color: e.target.value })} className="flex-1 bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
                </div>
                <p className="text-xs text-yellow-500">⚠ Saving will delete and re-create this tag</p>
                <div className="flex items-center gap-2">
                  <button onClick={() => saveEdit(item.id)} className="bg-indigo-500 hover:bg-indigo-400 px-3 py-1.5 rounded text-sm min-h-[36px]">Save</button>
                  <button onClick={() => setEditingId(null)} className="bg-gray-700 hover:bg-gray-600 px-3 py-1.5 rounded text-sm min-h-[36px]">Cancel</button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            ) : (
              <div key={item.id} className="flex items-center justify-between py-2 border-b border-gray-800/50">
                <div className="flex items-center gap-2">
                  <span className="h-4 w-4 rounded" style={{ backgroundColor: item.color }} />
                  <span className="text-sm text-gray-100">{item.name}</span>
                </div>
                <div className="flex items-center gap-2">
                  <button onClick={() => startEdit(item)} disabled={showAdd} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">Edit</button>
                  <button onClick={() => deleteItem(item.id)} className="text-xs text-red-400 hover:text-red-300 px-2 min-h-[36px]">Delete</button>
                </div>
              </div>
            )
          ))}
        </div>
      )}
      {showAdd ? (
        <div className="space-y-2 border-t border-gray-800 pt-4">
          <input placeholder="Name" value={addForm.name} onChange={e => setAddForm({ ...addForm, name: e.target.value })} className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          <div className="flex items-center gap-2">
            <input type="color" value={addForm.color} onChange={e => setAddForm({ ...addForm, color: e.target.value })} className="h-8 w-8 rounded cursor-pointer" />
            <input value={addForm.color} onChange={e => setAddForm({ ...addForm, color: e.target.value })} className="flex-1 bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-gray-100" />
          </div>
          <div className="flex gap-2">
            <button onClick={addItem} className="bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-sm font-semibold min-h-[36px]">Add</button>
            <button onClick={() => setShowAdd(false)} className="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded text-sm min-h-[36px]">Cancel</button>
          </div>
        </div>
      ) : (
        <button onClick={() => { setShowAdd(true); setEditingId(null) }} className="text-sm text-indigo-400 hover:text-indigo-300">+ Add Tag</button>
      )}
    </Section>
  )
}

/* -------------------------------------------------------------------------- */
/*  Scheduled Tasks Section                                                   */
/* -------------------------------------------------------------------------- */

function formatRelative(dateStr: string | null): string {
  if (!dateStr) return '—'
  const diff = Date.now() - new Date(dateStr).getTime()
  const minutes = Math.floor(diff / 60000)
  if (minutes < 60) return `${minutes}m ago`
  const hours = Math.floor(minutes / 60)
  if (hours < 24) return `${hours}h ago`
  const days = Math.floor(hours / 24)
  return `${days}d ago`
}

function formatNext(dateStr: string | null): string {
  if (!dateStr) return '—'
  const diff = new Date(dateStr).getTime() - Date.now()
  if (diff <= 0) return 'now'
  const minutes = Math.floor(diff / 60000)
  if (minutes < 60) return `in ${minutes}m`
  const hours = Math.floor(minutes / 60)
  if (hours < 24) return `in ${hours}h`
  return `in ${Math.floor(hours / 24)}d`
}

function TasksSection() {
  const { showToast } = useToast()
  const [items, setItems] = useState<TaskInfo[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  const fetch_ = useCallback(() => {
    setLoading(true); setError(null)
    fetchAPI<TaskInfo[]>('/api/workers')
      .then(d => setItems(d ?? []))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false))
  }, [])

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

  const triggerTask = async (name: string) => {
    try {
      await postAPI(`/api/workers/${encodeURIComponent(name)}/trigger`, {})
      showToast('Task triggered')
    } catch { showToast('Failed to trigger task') }
  }

  const toggleTask = async (task: TaskInfo) => {
    try {
      await putAPI(`/api/workers/${encodeURIComponent(task.name)}`, { enabled: !task.enabled })
      fetch_()
    } catch { showToast('Failed to toggle task') }
  }

  return (
    <Section title="Scheduled Tasks" loading={loading} error={error} onRetry={fetch_}>
      {items.length === 0 ? (
        <p className="text-gray-500 text-sm">No scheduled tasks.</p>
      ) : (
        <div className="space-y-2">
          {items.map(item => (
            <div key={item.id} className="flex items-center justify-between py-2 border-b border-gray-800/50">
<div className="min-w-0">
              <div className="flex items-center gap-2">
                <Toggle checked={item.enabled} onChange={() => toggleTask(item)} label={`${item.name}: ${item.enabled ? 'disable' : 'enable'}`} />
                <p className="text-sm text-gray-100">{item.name}</p>
                  <span className="text-xs text-gray-500">({item.cron_expr})</span>
                </div>
                <p className="text-xs text-gray-500 mt-1">
                  Last: {formatRelative(item.last_run_at)} • Next: {formatNext(item.next_run_at)}
                </p>
              </div>
              <button onClick={() => triggerTask(item.name)} className="text-xs text-indigo-400 hover:text-indigo-300 px-2 min-h-[36px]">
                Trigger Now
              </button>
            </div>
          ))}
        </div>
      )}
    </Section>
  )
}
