import { useEffect, useState } from "react"
import { Sliders, RotateCcw, Check, Loader2, MessageSquare, Code2 } from "lucide-react"
import { updateRoutingPolicy, type RoutingPolicy } from "@/lib/api"
import { useRoutingPolicy, useQueryClient, qk } from "@/lib/queries"
import { cn } from "@/lib/utils"

// Welche Policy-Felder zu welcher Lane gehören (Rest ist global).
const CHAT_FIELDS: (keyof RoutingPolicy)[] = ["fast", "heavy", "heavy_chars"]
const CODING_FIELDS: (keyof RoutingPolicy)[] = ["coder_lite", "coder", "coding_escalate_chars"]

export function LaneEditor() {
  const qc = useQueryClient()
  const { data: meta, isLoading } = useRoutingPolicy()
  const [draft, setDraft] = useState<RoutingPolicy | null>(null)
  const [saving, setSaving] = useState(false)
  const [err, setErr] = useState("")
  const [savedAt, setSavedAt] = useState(0)

  // Draft initialisieren, sobald die Policy geladen ist (und nicht überschreiben, wenn schon editiert).
  useEffect(() => {
    if (meta?.policy && !draft) setDraft({ ...meta.policy })
  }, [meta, draft])

  if (isLoading || !meta || !draft) {
    return (
      <div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-5 text-xs text-muted-foreground">
        Lade Routing-Policy…
      </div>
    )
  }

  const fieldSpec = (key: keyof RoutingPolicy) => meta.fields.find((f) => f.key === key)!
  const dirty = (Object.keys(draft) as (keyof RoutingPolicy)[]).some((k) => draft[k] !== meta.policy[k])

  const set = <K extends keyof RoutingPolicy>(key: K, value: RoutingPolicy[K]) => {
    setDraft((d) => (d ? { ...d, [key]: value } : d))
    setErr("")
  }
  const resetField = (key: keyof RoutingPolicy) => set(key, meta.defaults[key])

  async function save() {
    if (!draft) return
    const patch: Partial<RoutingPolicy> = {}
    for (const k of Object.keys(draft) as (keyof RoutingPolicy)[]) {
      if (draft[k] !== meta!.policy[k]) (patch as any)[k] = draft[k]
    }
    if (Object.keys(patch).length === 0) return
    setSaving(true)
    setErr("")
    try {
      const { policy } = await updateRoutingPolicy(patch)
      setDraft({ ...policy })
      qc.invalidateQueries({ queryKey: qk.routingPolicy })
      qc.invalidateQueries({ queryKey: qk.routing })
      setSavedAt(Date.now())
      setTimeout(() => setSavedAt(0), 2000)
    } catch (e: any) {
      setErr(e.message || String(e))
    } finally {
      setSaving(false)
    }
  }

  function Field({ k }: { k: keyof RoutingPolicy }) {
    const spec = fieldSpec(k)
    const val = draft![k]
    const isDefault = draft![k] === meta!.defaults[k]
    return (
      <div className="space-y-1">
        <div className="flex items-center justify-between gap-2">
          <label className="text-[10px] font-semibold text-muted-foreground">{spec.label}</label>
          {!isDefault && (
            <button
              onClick={() => resetField(k)}
              className="flex items-center gap-0.5 text-[9px] text-muted-foreground/60 hover:text-foreground transition-colors cursor-pointer"
              title={`Auf Default zurücksetzen (${String(meta!.defaults[k]) || "leer"})`}
            >
              <RotateCcw className="h-2.5 w-2.5" /> Default
            </button>
          )}
        </div>
        {spec.type === "bool" ? (
          <button
            onClick={() => set(k, !val as any)}
            className={cn(
              "flex h-8 w-full items-center justify-between rounded-lg border px-3 text-[11px] font-semibold transition-all cursor-pointer",
              val ? "border-emerald-500/40 bg-emerald-500/10 text-emerald-300" : "border-border/40 bg-background/40 text-muted-foreground",
            )}
          >
            <span>{val ? "An" : "Aus"}</span>
            <span className={cn("h-3.5 w-3.5 rounded-full transition-colors", val ? "bg-emerald-400" : "bg-muted-foreground/40")} />
          </button>
        ) : spec.type === "int" ? (
          <input
            type="number"
            value={val as number}
            min={spec.min}
            max={spec.max}
            onChange={(e) => set(k, Number(e.target.value) as any)}
            className="h-8 w-full rounded-lg border border-border/40 bg-background/40 px-3 font-mono text-[11px] text-foreground outline-none focus:border-primary/50"
          />
        ) : (
          <input
            type="text"
            value={val as string}
            placeholder={k === "coder_lite" ? "(leer = aus)" : ""}
            onChange={(e) => set(k, e.target.value as any)}
            className="h-8 w-full rounded-lg border border-border/40 bg-background/40 px-3 font-mono text-[11px] text-foreground outline-none focus:border-primary/50"
          />
        )}
      </div>
    )
  }

  return (
    <div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-5 shadow-lg shadow-black/10 space-y-4">
      <div className="flex items-center justify-between gap-3 flex-wrap">
        <div className="flex items-center gap-2">
          <Sliders className="h-4.5 w-4.5 text-primary" />
          <span className="text-xs font-bold uppercase tracking-wider text-foreground">Lane-Routing &amp; Policy</span>
          <span className="text-[9px] font-mono px-1.5 py-0.5 rounded bg-emerald-500/10 text-emerald-300 border border-emerald-500/20">hot-reload</span>
        </div>
        <div className="flex items-center gap-2">
          {err && <span className="text-[10px] text-red-400 max-w-[280px] truncate" title={err}>{err}</span>}
          {savedAt > 0 && (
            <span className="flex items-center gap-1 text-[10px] text-emerald-400"><Check className="h-3.5 w-3.5" /> gespeichert</span>
          )}
          <button
            onClick={save}
            disabled={!dirty || saving}
            className={cn(
              "h-8 px-4 rounded-lg text-[10px] font-bold uppercase tracking-wide transition-all flex items-center gap-1.5",
              dirty && !saving
                ? "bg-primary text-primary-foreground hover:opacity-90 cursor-pointer shadow-md shadow-primary/10"
                : "bg-background/40 text-muted-foreground/50 border border-border/40 cursor-not-allowed",
            )}
          >
            {saving ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : null}
            Speichern
          </button>
        </div>
      </div>

      <p className="text-[10px] text-muted-foreground/70 leading-relaxed -mt-1">
        Welches echte Modell hinter den virtuellen Lanes <code className="text-cyan-300">chat</code> und{" "}
        <code className="text-cyan-300">coding</code> steckt. Änderungen greifen sofort (kein Neustart). Die
        Keyword-Heuristiken bleiben im Code.
      </p>

      <div className="grid gap-4 md:grid-cols-2">
        {/* chat-Lane */}
        <div className="rounded-xl border border-border/40 bg-background/25 p-4 space-y-3">
          <div className="flex items-center gap-2 border-b border-border/30 pb-2">
            <MessageSquare className="h-4 w-4 text-teal-400" />
            <span className="text-[11px] font-bold uppercase tracking-wider text-foreground">chat</span>
            <span className="text-[9px] text-muted-foreground/60 font-mono">(= auto)</span>
          </div>
          {CHAT_FIELDS.map((k) => <Field key={k} k={k} />)}
        </div>

        {/* coding-Lane */}
        <div className="rounded-xl border border-border/40 bg-background/25 p-4 space-y-3">
          <div className="flex items-center gap-2 border-b border-border/30 pb-2">
            <Code2 className="h-4 w-4 text-indigo-400" />
            <span className="text-[11px] font-bold uppercase tracking-wider text-foreground">coding</span>
            <span className="text-[9px] text-muted-foreground/60 font-mono">(agentisch → immer Coder)</span>
          </div>
          {CODING_FIELDS.map((k) => <Field key={k} k={k} />)}
        </div>
      </div>

      {/* Globale Schalter */}
      <div className="rounded-xl border border-border/40 bg-background/25 p-4">
        <div className="max-w-xs"><Field k="fast_no_think" /></div>
      </div>
    </div>
  )
}
