"use client";
import { useEffect, useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { Captions, Loader2, Save, FolderOpen, CheckCircle2, AlertCircle, RefreshCw, Trash2, Sparkles } from "lucide-react";
import type { WhisperJavSettings as WhisperJavSettingsT } from "@/lib/db/appSettings";
import { setWhisperJavSettings } from "@/app/actions/settings";
import { useSettings } from "./SettingsProvider";
import { useSettingsPanel } from "./SettingsPanelProvider";
import { cn } from "@/lib/utils";

type Quality = WhisperJavSettingsT["quality"];
type SourceLang = WhisperJavSettingsT["sourceLanguage"];
type OutputMode = WhisperJavSettingsT["outputMode"];
type Sensitivity = WhisperJavSettingsT["sensitivity"];
type Location = WhisperJavSettingsT["outputLocation"];

interface VerifyResult {
  ok: boolean;
  version?: string;
  resolvedPath?: string;
  error?: string;
}

export function WhisperJavSettings() {
  const { settings } = useSettings();
  const w = settings.whisperjav;
  const router = useRouter();
  const { close: closeSettings } = useSettingsPanel();
  const [, start] = useTransition();
  const [draft, setDraft] = useState<WhisperJavSettingsT>(w);
  const [saving, setSaving] = useState(false);
  const [verifying, setVerifying] = useState(false);
  const [verify, setVerify] = useState<VerifyResult | null>(null);
  const [autodetected, setAutodetected] = useState(false);

  useEffect(() => { setDraft(w); }, [w]);

  // First-open autodetect — only when cliPath is empty AND no draft change.
  useEffect(() => {
    if (autodetected) return;
    if (draft.cliPath) return;
    setAutodetected(true);
    void (async () => {
      try {
        const r = await fetch("/api/whisperjav-verify", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ autodetect: true }),
        });
        const data = (await r.json()) as VerifyResult;
        if (data.ok && data.resolvedPath) {
          setDraft((cur) => (cur.cliPath ? cur : { ...cur, cliPath: data.resolvedPath! }));
          setVerify(data);
        }
      } catch { /* no autodetect available */ }
    })();
  }, [autodetected, draft.cliPath]);

  const dirty = JSON.stringify(draft) !== JSON.stringify(w);

  async function browse() {
    try {
      const r = await fetch("/api/pick-file", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ purpose: "whisperjav" }),
      });
      const data = await r.json();
      if (data.path) setDraft((cur) => ({ ...cur, cliPath: data.path }));
    } catch { /* ignore */ }
  }

  async function runVerify() {
    setVerifying(true);
    setVerify(null);
    try {
      const r = await fetch("/api/whisperjav-verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ path: draft.cliPath }),
      });
      const data = (await r.json()) as VerifyResult;
      setVerify(data);
    } catch (e) {
      setVerify({ ok: false, error: (e as Error).message });
    } finally {
      setVerifying(false);
    }
  }

  async function save() {
    setSaving(true);
    try {
      await setWhisperJavSettings(draft);
      start(() => router.refresh());
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="py-2 space-y-5">
      <div>
        <div className="text-sm font-medium mb-1 flex items-center gap-1.5">
          <Captions className="w-3.5 h-3.5 text-[var(--color-cyan)]" />
          WhisperJAV Subtitle Generator
        </div>
        <div className="text-xs text-[var(--color-fg-muted)] mb-2 max-w-2xl">
          Local AI subtitle generation. Configure the CLI path, then use{" "}
          <span className="font-mono">Generate Subtitles</span> from the player&apos;s subtitle dropdown.
          First run may download models (~1–2 GB).
        </div>
      </div>

      {/* CLI path */}
      <div>
        <div className="text-sm font-medium mb-1">CLI Path</div>
        <div className="flex items-center gap-2">
          <input
            type="text"
            value={draft.cliPath}
            onChange={(e) => setDraft({ ...draft, cliPath: e.target.value })}
            placeholder="whisperjav (or absolute path)"
            className="flex-1 glass rounded-lg px-3 py-1.5 text-sm font-mono outline-none focus:border-[var(--color-cyan)]"
          />
          <button
            type="button"
            onClick={browse}
            title="Browse for whisperjav.exe"
            className="inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg glass glass-hover"
          >
            <FolderOpen className="w-4 h-4" /> Browse
          </button>
          <button
            type="button"
            onClick={runVerify}
            disabled={verifying || !draft.cliPath.trim()}
            className="inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg glass glass-hover disabled:opacity-40"
          >
            {verifying ? <Loader2 className="w-4 h-4 animate-spin" /> : <RefreshCw className="w-4 h-4" />}
            Verify
          </button>
        </div>
        {verify && (
          <div className={cn(
            "mt-2 text-xs rounded-lg px-3 py-2 border",
            verify.ok
              ? "text-[var(--color-mint)] bg-[var(--color-mint)]/5 border-[var(--color-mint)]/25"
              : "text-red-300 bg-red-500/5 border-red-500/25",
          )}>
            <div className="flex items-start gap-2">
              {verify.ok
                ? <CheckCircle2 className="w-4 h-4 mt-0.5 shrink-0" />
                : <AlertCircle className="w-4 h-4 mt-0.5 shrink-0" />}
              <div className="min-w-0">
                {verify.ok
                  ? <>Detected: <strong>WhisperJAV {verify.version}</strong> at <span className="font-mono break-all">{verify.resolvedPath}</span></>
                  : <>Verify failed: {verify.error}</>}
              </div>
            </div>
          </div>
        )}
      </div>

      {/* Quality */}
      <RadioGroup<Quality>
        label="Quality"
        value={draft.quality}
        onChange={(v) => setDraft({ ...draft, quality: v })}
        options={[
          { value: "fast", title: "Fast", desc: "Quickest pass; lower fidelity." },
          { value: "balanced", title: "Balanced", desc: "Default. Good speed/quality tradeoff." },
          { value: "qwen", title: "Best (Qwen)", desc: "Qwen3-ASR with JAV-tuned post-processing. Slow + heavy on VRAM." },
        ]}
      />

      {/* Source language + Output mode */}
      <div className="grid grid-cols-1 md:grid-cols-2 gap-5">
        <RadioGroup<SourceLang>
          label="Source Language"
          value={draft.sourceLanguage}
          onChange={(v) => setDraft({ ...draft, sourceLanguage: v })}
          options={[
            { value: "japanese", title: "Japanese", desc: "" },
            { value: "korean", title: "Korean", desc: "" },
            { value: "chinese", title: "Chinese", desc: "" },
            { value: "english", title: "English", desc: "" },
          ]}
        />
        <RadioGroup<OutputMode>
          label="Output Mode"
          value={draft.outputMode}
          onChange={(v) => setDraft({ ...draft, outputMode: v })}
          options={[
            { value: "native", title: "Native", desc: "Transcribe in source language." },
            { value: "direct-to-english", title: "Direct To English", desc: "Whisper-translate to English." },
          ]}
        />
      </div>

      <div className="grid grid-cols-1 md:grid-cols-2 gap-5">
        <RadioGroup<Sensitivity>
          label="Sensitivity"
          value={draft.sensitivity}
          onChange={(v) => setDraft({ ...draft, sensitivity: v })}
          options={[
            { value: "conservative", title: "Conservative", desc: "" },
            { value: "balanced", title: "Balanced", desc: "" },
            { value: "aggressive", title: "Aggressive", desc: "" },
          ]}
        />
        <RadioGroup<Location>
          label="Output Location"
          value={draft.outputLocation}
          onChange={(v) => setDraft({ ...draft, outputLocation: v })}
          options={[
            { value: "beside-video", title: "Beside Video", desc: "Falls back to data folder if read-only." },
            { value: "data-folder", title: "Data Folder", desc: "data/generated-subtitles/<code>/" },
          ]}
        />
      </div>

      <label className="flex items-center gap-2 text-sm cursor-pointer">
        <input
          type="checkbox"
          checked={draft.noSignature}
          onChange={(e) => setDraft({ ...draft, noSignature: e.target.checked })}
        />
        Disable WhisperJAV signature cue at end of subtitles
      </label>

      <div>
        <div className="text-sm font-medium mb-1">Job History Retention</div>
        <div className="text-xs text-[var(--color-fg-muted)] mb-2 max-w-2xl">
          Days to keep failed and cancelled job temp folders for debugging.
          Successful job folders are deleted immediately.{" "}
          <span className="font-mono">0</span> = keep forever.
        </div>
        <div className="flex items-center gap-2">
          <input
            type="number"
            min={0}
            value={draft.retentionDays}
            onChange={(e) => setDraft({ ...draft, retentionDays: Math.max(0, Number(e.target.value) || 0) })}
            className="w-24 glass rounded-lg px-3 py-1.5 text-sm font-mono outline-none focus:border-[var(--color-cyan)]"
          />
          <span className="text-xs text-[var(--color-fg-dim)]">days</span>
        </div>
      </div>

      <div className="flex items-center gap-2 pt-3 border-t border-[var(--color-glass-border)] flex-wrap">
        <button
          type="button"
          onClick={save}
          disabled={!dirty || saving}
          className="inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg bg-[var(--color-cyan)] text-black font-medium disabled:opacity-40 disabled:cursor-not-allowed"
        >
          {saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
          Save
        </button>
        <Link
          href="/subtitles/batch"
          onClick={closeSettings}
          className="inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg glass glass-hover"
        >
          <Sparkles className="w-4 h-4 text-[var(--color-cyan)]" />
          Open Batch Generator
        </Link>
        <ClearHistoryButton />
      </div>
    </div>
  );
}

function ClearHistoryButton() {
  const [busy, setBusy] = useState(false);
  const [result, setResult] = useState<string | null>(null);
  async function clearAll() {
    if (!window.confirm("Clear all WhisperJAV job history? Temp folders for past jobs will be deleted.")) return;
    setBusy(true);
    setResult(null);
    try {
      const r = await fetch("/api/whisperjav-jobs", { method: "DELETE" });
      const data = (await r.json()) as { rows?: number; dirs?: number };
      setResult(`Removed ${data.rows ?? 0} row(s), ${data.dirs ?? 0} folder(s).`);
    } catch (e) {
      setResult(`Failed: ${(e as Error).message}`);
    } finally {
      setBusy(false);
    }
  }
  return (
    <>
      <button
        type="button"
        onClick={clearAll}
        disabled={busy}
        className="inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg border border-red-500/30 text-red-300 hover:bg-red-500/10 disabled:opacity-40"
      >
        {busy ? <Loader2 className="w-4 h-4 animate-spin" /> : <Trash2 className="w-4 h-4" />}
        Clear Job History
      </button>
      {result && <span className="text-xs text-[var(--color-fg-dim)]">{result}</span>}
    </>
  );
}

function RadioGroup<T extends string>({ label, value, onChange, options }: {
  label: string;
  value: T;
  onChange: (v: T) => void;
  options: Array<{ value: T; title: string; desc: string }>;
}) {
  return (
    <div>
      <div className="text-sm font-medium mb-1">{label}</div>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
        {options.map((opt) => {
          const active = value === opt.value;
          return (
            <button
              key={opt.value}
              type="button"
              onClick={() => onChange(opt.value)}
              className={cn(
                "text-left rounded-lg border px-3 py-2 transition-colors cursor-pointer",
                active
                  ? "border-[var(--color-cyan)] bg-[var(--color-cyan)]/10 shadow-[var(--shadow-glow-cyan)]"
                  : "border-[var(--color-glass-border)] bg-[var(--color-glass)]/30 hover:border-[var(--color-glass-border-strong)]",
              )}
            >
              <div className={cn(
                "text-sm font-medium",
                active ? "text-[var(--color-cyan)]" : "text-[var(--color-fg)]",
              )}>{opt.title}</div>
              {opt.desc && (
                <div className="text-[11px] text-[var(--color-fg-muted)] mt-0.5 leading-snug">{opt.desc}</div>
              )}
            </button>
          );
        })}
      </div>
    </div>
  );
}
