// frontend\src\components\ui\RecorderSettings.tsx
'use client'

import { useEffect, useRef, useState } from 'react'
import Button from './Button'
import Card from './Card'
import LabeledSwitch from './LabeledSwitch'
import Task from './Task'
import TaskList from './TaskList'
import type { TaskItem } from './TaskList'

type RecorderSettings = {
  recordDir: string
  doneDir: string
  ffmpegPath?: string
  autoAddToDownloadList?: boolean
  autoStartAddedDownloads?: boolean
  useChaturbateApi?: boolean
  useMyFreeCamsWatcher?: boolean
  autoDeleteSmallDownloads?: boolean
  autoDeleteSmallDownloadsBelowMB?: number
  blurPreviews?: boolean
  teaserPlayback?: 'still' | 'hover' | 'all'
  teaserAudio?: boolean
  lowDiskPauseBelowGB?: number
  enableNotifications?: boolean
}

type DiskStatus = {
  emergency: boolean
  pauseGB: number
  resumeGB: number
  freeBytes: number
  freeBytesHuman: string
  recordPath?: string
}


const DEFAULTS: RecorderSettings = {
  recordDir: 'records',
  doneDir: 'records/done',
  ffmpegPath: '',
  autoAddToDownloadList: true,
  useChaturbateApi: false,
  useMyFreeCamsWatcher: false,
  autoDeleteSmallDownloads: true,
  autoDeleteSmallDownloadsBelowMB: 200,
  blurPreviews: false,
  teaserPlayback: 'hover',
  teaserAudio: false,
  lowDiskPauseBelowGB: 5,
  enableNotifications: true,
}

type Props = {
  onAssetsGenerated?: () => void
}

function shortTaskFilename(name?: string, max = 52) {
  const s = String(name ?? '').trim()
  if (!s) return ''
  if (s.length <= max) return s
  return '…' + s.slice(-(max - 1))
}

export default function RecorderSettings({ onAssetsGenerated }: Props) {
  const [value, setValue] = useState<RecorderSettings>(DEFAULTS)
  const [saving, setSaving] = useState(false)
  const [cleaning, setCleaning] = useState(false)
  const [browsing, setBrowsing] = useState<'record' | 'done' | 'ffmpeg' | null>(null)
  const [msg, setMsg] = useState<string | null>(null)
  const [err, setErr] = useState<string | null>(null)
  const [diskStatus, setDiskStatus] = useState<DiskStatus | null>(null)
    // ✅ Tasklist (Assets generieren)
  const assetsAbortRef = useRef<AbortController | null>(null)

  const [assetsTask, setAssetsTask] = useState<TaskItem>({
    id: 'generate-assets',
    status: 'idle',
    title: 'Assets generieren',     // oder '' wenn du es komplett weg willst
    text: '',
    cancellable: true,
    fading: false,
  })

  const [cleanupTask, setCleanupTask] = useState<TaskItem>({
    id: 'cleanup',
    status: 'idle',
    title: 'Aufräumen',
    text: '',
    cancellable: false,
    fading: false,
  })

  const pauseGB = Number(value.lowDiskPauseBelowGB ?? DEFAULTS.lowDiskPauseBelowGB ?? 5)
  const uiPauseGB = diskStatus?.pauseGB ?? pauseGB
  const uiResumeGB = diskStatus?.resumeGB ?? (pauseGB + 3)


  useEffect(() => {
    let alive = true
    fetch('/api/settings', { cache: 'no-store' })
      .then(async (r) => {
        if (!r.ok) throw new Error(await r.text())
        return r.json()
      })
      .then((data: RecorderSettings) => {
        if (!alive) return
        setValue({
          recordDir: (data.recordDir || DEFAULTS.recordDir).toString(),
          doneDir: (data.doneDir || DEFAULTS.doneDir).toString(),
          ffmpegPath: String(data.ffmpegPath ?? DEFAULTS.ffmpegPath ?? ''),


          // ✅ falls backend die Felder noch nicht hat -> defaults nutzen
          autoAddToDownloadList: data.autoAddToDownloadList ?? DEFAULTS.autoAddToDownloadList,
          autoStartAddedDownloads: data.autoStartAddedDownloads ?? DEFAULTS.autoStartAddedDownloads,

          useChaturbateApi: data.useChaturbateApi ?? DEFAULTS.useChaturbateApi,
          useMyFreeCamsWatcher: data.useMyFreeCamsWatcher ?? DEFAULTS.useMyFreeCamsWatcher,
          autoDeleteSmallDownloads: data.autoDeleteSmallDownloads ?? DEFAULTS.autoDeleteSmallDownloads,
          autoDeleteSmallDownloadsBelowMB: data.autoDeleteSmallDownloadsBelowMB ?? DEFAULTS.autoDeleteSmallDownloadsBelowMB,
          blurPreviews: data.blurPreviews ?? DEFAULTS.blurPreviews,
          teaserPlayback: (data as any).teaserPlayback ?? DEFAULTS.teaserPlayback,
          teaserAudio: (data as any).teaserAudio ?? DEFAULTS.teaserAudio,
          lowDiskPauseBelowGB: (data as any).lowDiskPauseBelowGB ?? DEFAULTS.lowDiskPauseBelowGB,
          enableNotifications: (data as any).enableNotifications ?? DEFAULTS.enableNotifications,
        })
      })
      .catch(() => {
        // backend evtl. noch alt -> defaults lassen
      })
    return () => {
      alive = false
    }
  }, [])

  useEffect(() => {
    let alive = true
    const load = async () => {
      try {
        const r = await fetch('/api/status/disk', { cache: 'no-store' })
        if (!r.ok) return
        const data = (await r.json()) as DiskStatus
        if (alive) setDiskStatus(data)
      } catch {
        // ignorieren
      }
    }

    load()
    const t = window.setInterval(load, 5000) // alle 5s aktualisieren
    return () => {
      alive = false
      window.clearInterval(t)
    }
  }, [])

  async function browse(target: 'record' | 'done' | 'ffmpeg') {
    setErr(null)
    setMsg(null)
    setBrowsing(target)

    try {
      window.focus()
      const res = await fetch(`/api/settings/browse?target=${target}`, { cache: 'no-store' })
      if (res.status === 204) return // user cancelled
      if (!res.ok) {
        const t = await res.text().catch(() => '')
        throw new Error(t || `HTTP ${res.status}`)
      }

      const data = (await res.json()) as { path?: string }
      const p = (data.path ?? '').trim()
      if (!p) return

      setValue((v) => {
        if (target === 'record') return { ...v, recordDir: p }
        if (target === 'done') return { ...v, doneDir: p }
        return { ...v, ffmpegPath: p }
      })
    } catch (e: any) {
      setErr(e?.message ?? String(e))
    } finally {
      setBrowsing(null)
    }
  }

  async function save() {
    setErr(null)
    setMsg(null)

    const recordDir = value.recordDir.trim()
    const doneDir = value.doneDir.trim()
    const ffmpegPath = (value.ffmpegPath ?? '').trim()

    if (!recordDir || !doneDir) {
      setErr('Bitte Aufnahme-Ordner und Ziel-Ordner angeben.')
      return
    }

    // ✅ Switch-Logik: Autostart nur sinnvoll, wenn Auto-Add aktiv ist
    const autoAddToDownloadList = !!value.autoAddToDownloadList
    const autoStartAddedDownloads = autoAddToDownloadList ? !!value.autoStartAddedDownloads : false

    const useChaturbateApi = !!value.useChaturbateApi
    const useMyFreeCamsWatcher = !!value.useMyFreeCamsWatcher
    const autoDeleteSmallDownloads = !!value.autoDeleteSmallDownloads
    const autoDeleteSmallDownloadsBelowMB = Math.max(
      0,
      Math.min(100_000, Math.floor(Number(value.autoDeleteSmallDownloadsBelowMB ?? DEFAULTS.autoDeleteSmallDownloadsBelowMB)))
    )
    const blurPreviews = !!value.blurPreviews
    const teaserPlayback =
      value.teaserPlayback === 'still' || value.teaserPlayback === 'all' || value.teaserPlayback === 'hover'
        ? value.teaserPlayback
        : DEFAULTS.teaserPlayback
    const teaserAudio = !!value.teaserAudio
    const lowDiskPauseBelowGB = Math.max(1, Math.floor(Number(value.lowDiskPauseBelowGB ?? DEFAULTS.lowDiskPauseBelowGB)))
    const enableNotifications = !!value.enableNotifications

    setSaving(true)
    try {
      const res = await fetch('/api/settings', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          recordDir,
          doneDir,
          ffmpegPath,
          autoAddToDownloadList,
          autoStartAddedDownloads,
          useChaturbateApi,
          useMyFreeCamsWatcher,
          autoDeleteSmallDownloads,
          autoDeleteSmallDownloadsBelowMB,
          blurPreviews,
          teaserPlayback,
          teaserAudio,
          lowDiskPauseBelowGB,
          enableNotifications,
        }),
      })
      if (!res.ok) {
        const t = await res.text().catch(() => '')
        throw new Error(t || `HTTP ${res.status}`)
      }
      setMsg('✅ Gespeichert.')
      window.dispatchEvent(new CustomEvent('recorder-settings-updated'))
    } catch (e: any) {
      setErr(e?.message ?? String(e))
    } finally {
      setSaving(false)
    }
  }

  function fadeOutTask(setter: React.Dispatch<React.SetStateAction<TaskItem>>, delayMs = 3500, fadeMs = 500) {
    window.setTimeout(() => {
      setter((t) => ({ ...t, fading: true }))
      window.setTimeout(() => {
        setter((t) => ({ ...t, status: 'idle', text: '', err: undefined, done: 0, total: 0, fading: false }))
      }, fadeMs)
    }, delayMs)
  }

  async function cleanupSmallDone() {
    setErr(null)
    setMsg(null)

    const mb = Number(value.autoDeleteSmallDownloadsBelowMB ?? DEFAULTS.autoDeleteSmallDownloadsBelowMB ?? 0)
    const doneDir = (value.doneDir || DEFAULTS.doneDir).trim()

    if (!doneDir) {
      setErr('doneDir ist leer.')
      return
    }
    if (!mb || mb <= 0) {
      setErr('Mindestgröße ist 0 – es würde nichts gelöscht.')
      return
    }

    const ok = window.confirm(
      `Aufräumen:\n` +
        `• Löscht Dateien in "${doneDir}" < ${mb} MB (Ordner "keep" wird übersprungen)\n` +
        `• Entfernt verwaiste Previews/Thumbs/Generated-Assets ohne passende Datei\n\n` +
        `Fortfahren?`
    )
    if (!ok) return

    // ✅ Task starten (als letzter Eintrag in TaskList)
    setCleaning(true)
    setCleanupTask((t) => ({
      ...t,
      status: 'running',
      title: 'Aufräumen',          // ✅ HINZUFÜGEN (reset)
      text: 'Räume auf…',
      err: undefined,
      done: 0,
      total: 1,
      fading: false,
    }))

    try {
      const res = await fetch('/api/settings/cleanup', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        cache: 'no-store',
      })
      if (!res.ok) {
        const t = await res.text().catch(() => '')
        throw new Error(t || `HTTP ${res.status}`)
      }

      const data = await res.json()

      const scannedFiles = Number(data.scannedFiles ?? 0)

      const orphanRemoved = Number(data.orphanIdsRemoved ?? 0)
      const genRemoved = Number(data.generatedOrphansRemoved ?? 0)

      const orphansTotalRemoved = orphanRemoved + genRemoved

      setCleanupTask((t) => ({
        ...t,
        status: 'done',
        done: 1,
        total: 1,
        title: 'Aufräumen',
        text: `geprüft: ${scannedFiles} · Orphans: ${orphansTotalRemoved}`,
      }))

      fadeOutTask(setCleanupTask) // ✅ nach und nach ausfaden
    } catch (e: any) {
      const msg = e?.message ?? String(e)
      setErr(msg)

      setCleanupTask((t) => ({
        ...t,
        status: 'error',
        text: 'Fehler beim Aufräumen.',
        err: msg,
      }))

      fadeOutTask(setCleanupTask)
    } finally {
      setCleaning(false)
    }
  }

  async function cancelAssetsTask() {
    const ac = assetsAbortRef.current
    assetsAbortRef.current = null

    // UI sofort
    setAssetsTask((t: TaskItem) => ({ ...t, status: 'cancelled', text: 'Abgebrochen.' }))

    if (ac) {
      ac.abort()
      return
    }

    // Fallback (z.B. nach Reload, wenn kein Controller existiert):
    try {
      await fetch('/api/tasks/generate-assets', { method: 'DELETE', cache: 'no-store' as any })
    } catch {
      // ignore
    }
  }

  return (
    <Card
      header={
        <div className="flex items-center justify-between gap-4">
          <div>
            <div className="text-base font-semibold text-gray-900 dark:text-white">Einstellungen</div>
            <div className="mt-0.5 text-xs text-gray-600 dark:text-gray-300">
              Recorder-Konfiguration, Automatisierung und Tasks.
            </div>
          </div>
          <Button variant="primary" onClick={save} disabled={saving}>
            Speichern
          </Button>
        </div>
      }
      grayBody
    >
      <div className="space-y-4">
        <TaskList
          tasks={[assetsTask, cleanupTask]}   // ✅ cleanupTask ist “am Ende”
          onCancel={(id: string) => {
            if (id === 'generate-assets') cancelAssetsTask()
          }}
        />

        {/* Alerts */}
        {err && (
          <div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-200">
            {err}
          </div>
        )}
        {msg && (
          <div className="rounded-lg border border-green-200 bg-green-50 px-3 py-2 text-sm text-green-700 dark:border-green-500/30 dark:bg-green-500/10 dark:text-green-200">
            {msg}
          </div>
        )}

        {/* Aufgaben */}
        <div className="rounded-2xl border border-gray-200 bg-white p-4 shadow-sm dark:border-white/10 dark:bg-gray-950/40">
          <div className="flex items-start justify-between gap-4">
            <div className="min-w-0">
              <div className="text-sm font-semibold text-gray-900 dark:text-white">Aufgaben</div>
              <div className="mt-1 text-xs text-gray-600 dark:text-gray-300">
                Hintergrundaufgaben wie z.B. Asset/Preview-Generierung.
              </div>
            </div>
          </div>

          <div className="mt-3 space-y-3">
            <Task
              title="Assets-Generator"
              description="Erzeugt fehlende Assets (thumb/preview/meta). Fortschritt & Abbrechen oben in der Taskliste."
              startLabel="Start"
              startingLabel="Starte…"
              startUrl="/api/tasks/generate-assets"
              stopUrl="/api/tasks/generate-assets"
              sseUrl="/api/tasks/assets/stream"
              onFinished={onAssetsGenerated}
              onStart={(ac) => {
                assetsAbortRef.current = ac
                setAssetsTask((t: TaskItem) => ({
                  ...t,
                  status: 'running',
                  title: 'Assets generieren',
                  text: '',
                  done: 0,
                  total: 0,
                  err: undefined,
                  fading: false,
                }))
              }}
              onProgress={(p) => {
                const fn = shortTaskFilename(p.currentFile)

                setAssetsTask((t: TaskItem) => ({
                  ...t,
                  status: 'running',
                  title: 'Assets generieren',
                  text: fn || '',
                  done: p.done,
                  total: p.total,
                }))
              }}
              onDone={() => {
                assetsAbortRef.current = null
                setAssetsTask((t: TaskItem) => ({ ...t, status: 'done', title: 'Assets generieren' }))
                fadeOutTask(setAssetsTask)
              }}
              onCancelled={() => {
                assetsAbortRef.current = null
                setAssetsTask((t: TaskItem) => ({
                  ...t,
                  status: 'cancelled',
                  title: 'Assets generieren',
                  text: 'Abgebrochen.',
                }))
                fadeOutTask(setAssetsTask)
              }}
              onError={(message) => {
                assetsAbortRef.current = null
                setAssetsTask((t: TaskItem) => ({
                  ...t,
                  status: 'error',
                  title: 'Assets generieren',
                  text: 'Fehler beim Generieren.',
                  err: message,
                }))
                fadeOutTask(setAssetsTask)
              }}
            />

            <Task
              title="Aufräumen"
              description='Löscht Dateien im doneDir kleiner als die Mindestgröße (Ordner "keep" wird übersprungen) und entfernt verwaiste Assets.'
              startLabel="Aufräumen"
              startingLabel="Läuft…"
              onTrigger={cleanupSmallDone}
              busy={cleaning}
              disabled={saving || !value.autoDeleteSmallDownloads}
              onError={(message) => {
                // Optional: zusätzlicher Fallback für Startfehler-Anzeige direkt im Task
                setErr(message)
              }}
            />
          </div>
        </div>

        {/* Paths */}
        <div className="rounded-2xl border border-gray-200 bg-white p-4 shadow-sm dark:border-white/10 dark:bg-gray-950/40">
          <div className="mb-3">
            <div className="text-sm font-semibold text-gray-900 dark:text-white">Pfad-Einstellungen</div>
            <div className="mt-1 text-xs text-gray-600 dark:text-gray-300">
              Aufnahme- und Zielverzeichnisse sowie optionaler ffmpeg-Pfad.
            </div>
          </div>

          <div className="space-y-3">
            {/* Aufnahme-Ordner */}
            <div className="grid grid-cols-1 gap-2 sm:grid-cols-12 sm:items-center">
              <label className="text-sm font-medium text-gray-900 dark:text-gray-200 sm:col-span-3">
                Aufnahme-Ordner
              </label>
              <div className="sm:col-span-9 flex gap-2">
                <input
                  value={value.recordDir}
                  onChange={(e) => setValue((v) => ({ ...v, recordDir: e.target.value }))}
                  placeholder="records  (oder absolut: C:\records / /mnt/data/records)"
                  className="min-w-0 flex-1 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200
                            focus:outline-none focus:ring-2 focus:ring-indigo-500
                            dark:bg-white/10 dark:text-white dark:ring-white/10"
                />
                <Button variant="secondary" onClick={() => browse('record')} disabled={saving || browsing !== null}>
                  Durchsuchen...
                </Button>
              </div>
            </div>

            {/* Fertige Downloads */}
            <div className="grid grid-cols-1 gap-2 sm:grid-cols-12 sm:items-center">
              <label className="text-sm font-medium text-gray-900 dark:text-gray-200 sm:col-span-3">
                Fertige Downloads nach
              </label>
              <div className="sm:col-span-9 flex gap-2">
                <input
                  value={value.doneDir}
                  onChange={(e) => setValue((v) => ({ ...v, doneDir: e.target.value }))}
                  placeholder="records/done"
                  className="min-w-0 flex-1 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200
                            focus:outline-none focus:ring-2 focus:ring-indigo-500
                            dark:bg-white/10 dark:text-white dark:ring-white/10"
                />
                <Button variant="secondary" onClick={() => browse('done')} disabled={saving || browsing !== null}>
                  Durchsuchen...
                </Button>
              </div>
            </div>

            {/* ffmpeg.exe */}
            <div className="grid grid-cols-1 gap-2 sm:grid-cols-12 sm:items-center">
              <label className="text-sm font-medium text-gray-900 dark:text-gray-200 sm:col-span-3">
                ffmpeg.exe
              </label>
              <div className="sm:col-span-9 flex gap-2">
                <input
                  value={value.ffmpegPath ?? ''}
                  onChange={(e) => setValue((v) => ({ ...v, ffmpegPath: e.target.value }))}
                  placeholder="Leer = automatisch (FFMPEG_PATH / ffmpeg im PATH)"
                  className="min-w-0 flex-1 rounded-lg px-3 py-2 text-sm bg-white text-gray-900 ring-1 ring-gray-200
                            focus:outline-none focus:ring-2 focus:ring-indigo-500
                            dark:bg-white/10 dark:text-white dark:ring-white/10"
                />
                <Button variant="secondary" onClick={() => browse('ffmpeg')} disabled={saving || browsing !== null}>
                  Durchsuchen...
                </Button>
              </div>
            </div>
          </div>
        </div>

        {/* Automatisierung */}
        <div className="rounded-2xl border border-gray-200 bg-white p-4 shadow-sm dark:border-white/10 dark:bg-gray-950/40">
          <div className="mb-3">
            <div className="text-sm font-semibold text-gray-900 dark:text-white">Automatisierung & Anzeige</div>
            <div className="mt-1 text-xs text-gray-600 dark:text-gray-300">
              Verhalten beim Hinzufügen/Starten sowie Anzeigeoptionen.
            </div>
          </div>

          <div className="space-y-3">
            <LabeledSwitch
              checked={!!value.autoAddToDownloadList}
              onChange={(checked) =>
                setValue((v) => ({
                  ...v,
                  autoAddToDownloadList: checked,
                  autoStartAddedDownloads: checked ? v.autoStartAddedDownloads : false,
                }))
              }
              label="Automatisch zur Downloadliste hinzufügen"
              description="Neue Links/Modelle werden automatisch in die Downloadliste übernommen."
            />

            <LabeledSwitch
              checked={!!value.autoStartAddedDownloads}
              onChange={(checked) => setValue((v) => ({ ...v, autoStartAddedDownloads: checked }))}
              disabled={!value.autoAddToDownloadList}
              label="Hinzugefügte Downloads automatisch starten"
              description="Wenn ein Download hinzugefügt wurde, startet er direkt (sofern möglich)."
            />

            <LabeledSwitch
              checked={!!value.useChaturbateApi}
              onChange={(checked) => setValue((v) => ({ ...v, useChaturbateApi: checked }))}
              label="Chaturbate API"
              description="Wenn aktiv, pollt das Backend alle paar Sekunden die Online-Rooms API und cached die aktuell online Models."
            />

            <LabeledSwitch
              checked={!!value.useMyFreeCamsWatcher}
              onChange={(checked) => setValue((v) => ({ ...v, useMyFreeCamsWatcher: checked }))}
              label="MyFreeCams Auto-Check (watched)"
              description="Geht watched MyFreeCams-Models einzeln durch und startet einen Download. Wenn keine Output-Datei entsteht, ist der Stream nicht öffentlich (offline/away/private) und der Job wird wieder entfernt."
            />

            {/* ✅ NEU: Auto-Delete kleine Downloads */}
            <div className="rounded-xl border border-gray-200 bg-gray-50 p-3 dark:border-white/10 dark:bg-white/5">
              <LabeledSwitch
                checked={!!value.autoDeleteSmallDownloads}
                onChange={(checked) =>
                  setValue((v) => ({
                    ...v,
                    autoDeleteSmallDownloads: checked,
                    autoDeleteSmallDownloadsBelowMB:
                      v.autoDeleteSmallDownloadsBelowMB ?? 50,
                  }))
                }
                label="Kleine Downloads automatisch löschen"
                description="Löscht fertige Downloads automatisch, wenn die Datei kleiner als die eingestellte Mindestgröße ist."
              />

              <div
                className={
                  'mt-2 grid grid-cols-1 gap-2 sm:grid-cols-12 sm:items-center ' +
                  (!value.autoDeleteSmallDownloads ? 'opacity-50 pointer-events-none' : '')
                }
              >
                <div className="sm:col-span-4">
                  <div className="text-sm font-medium text-gray-900 dark:text-gray-200">Mindestgröße</div>
                  <div className="text-xs text-gray-600 dark:text-gray-300">Alles darunter wird gelöscht.</div>
                </div>

                <div className="sm:col-span-8">
                  <div className="flex items-center justify-end gap-2">
                    <input
                      type="number"
                      min={0}
                      step={1}
                      value={value.autoDeleteSmallDownloadsBelowMB ?? 50}
                      onChange={(e) =>
                        setValue((v) => ({
                          ...v,
                          autoDeleteSmallDownloadsBelowMB: Number(e.target.value || 0),
                        }))
                      }
                      className="h-9 w-32 rounded-md border border-gray-200 bg-white px-3 text-sm text-gray-900 shadow-sm
                                dark:border-white/10 dark:bg-gray-900 dark:text-gray-100"
                    />

                    <span className="shrink-0 text-xs text-gray-600 dark:text-gray-300">MB</span>
                  </div>
                </div>
              </div>
            </div>

            <LabeledSwitch
              checked={!!value.blurPreviews}
              onChange={(checked) => setValue((v) => ({ ...v, blurPreviews: checked }))}
              label="Vorschaubilder blurren"
              description="Weichzeichnet Vorschaubilder/Teaser (praktisch auf mobilen Geräten oder im öffentlichen Umfeld)."
            />

            <div className="grid grid-cols-1 gap-2 sm:grid-cols-12 sm:items-center">
              <div className="sm:col-span-4">
                <div className="text-sm font-medium text-gray-900 dark:text-gray-200">Teaser abspielen</div>
                <div className="text-xs text-gray-600 dark:text-gray-300">
                  Standbild spart Leistung. „Bei Hover (Standard)“: Desktop spielt bei Hover ab, Mobile im Viewport. „Alle“ kann viel CPU ziehen.
                </div>
              </div>

              <div className="sm:col-span-8">
                <label className="sr-only" htmlFor="teaserPlayback">Teaser abspielen</label>
                <select
                  id="teaserPlayback"
                  value={value.teaserPlayback ?? 'hover'}
                  onChange={(e) => setValue((v) => ({ ...v, teaserPlayback: e.target.value as any }))}
                  className="h-9 w-full rounded-md border border-gray-200 bg-white px-3 text-sm text-gray-900 shadow-sm
                            dark:border-white/10 dark:bg-gray-900 dark:text-gray-100 dark:[color-scheme:dark]"
                >
                  <option value="still">Standbild</option>
                  <option value="hover">Bei Hover (Standard)</option>
                  <option value="all">Alle</option>
                </select>
              </div>
            </div>

            <LabeledSwitch
              checked={!!value.teaserAudio}
              onChange={(checked) => setValue((v) => ({ ...v, teaserAudio: checked }))}
              label="Teaser mit Ton"
              description="Wenn aktiv, werden Vorschau/Teaser nicht stumm geschaltet."
            />

            <LabeledSwitch
              checked={!!value.enableNotifications}
              onChange={(checked) => setValue((v) => ({ ...v, enableNotifications: checked }))}
              label="Benachrichtigungen"
              description="Wenn aktiv, zeigt das Frontend Toasts (z.B. wenn watched Models online/live gehen oder wenn ein queued Model wieder public wird)."
            />

            <div className="rounded-xl border border-gray-200 bg-gray-50 p-3 dark:border-white/10 dark:bg-white/5">
              <div className="flex items-start justify-between gap-3">
                <div>
                  <div className="text-sm font-semibold text-gray-900 dark:text-white">Speicherplatz-Notbremse</div>
                  <div className="mt-1 text-xs text-gray-600 dark:text-gray-300">
                    Aktiviert automatisch Stop + Autostart-Block bei wenig freiem Speicher (Resume bei +3 GB).
                  </div>
                </div>

                <span
                  className={
                    'inline-flex items-center rounded-full px-2 py-1 text-[11px] font-medium ' +
                    (diskStatus?.emergency
                      ? 'bg-red-100 text-red-800 dark:bg-red-500/20 dark:text-red-200'
                      : 'bg-green-100 text-green-800 dark:bg-green-500/20 dark:text-green-200')
                  }
                  title={diskStatus?.emergency ? 'Notfallbremse greift gerade' : 'OK'}
                >
                  {diskStatus?.emergency ? 'AKTIV' : 'OK'}
                </span>
              </div>

              <div className="mt-3 text-sm text-gray-900 dark:text-gray-200">
                <div>
                  <span className="font-medium">Schwelle:</span>{' '}
                  Pause unter <span className="tabular-nums">{uiPauseGB}</span> GB
                  {' · '}Resume ab{' '}
                  <span className="tabular-nums">
                    {uiResumeGB}
                  </span>{' '}
                  GB
                </div>

                <div className="mt-1 text-xs text-gray-600 dark:text-gray-300">
                  {diskStatus
                    ? `Frei: ${diskStatus.freeBytesHuman}${diskStatus.recordPath ? ` (Pfad: ${diskStatus.recordPath})` : ''}`
                    : 'Status wird geladen…'}
                </div>

                {diskStatus?.emergency && (
                  <div className="mt-2 text-xs text-red-700 dark:text-red-200">
                    Notfallbremse greift: laufende Downloads werden gestoppt und Autostart bleibt gesperrt, bis wieder genug frei ist.
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </Card>
  )
}
