"use client";
import { useEffect, useState, useRef } from "react";
import { Plus, Trash2, RotateCcw, Save, ChevronDown, ChevronUp, Pencil } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { type Persona } from "@/lib/personas";

function uid() {
  return Math.random().toString(36).slice(2, 10);
}

// ── Confirm dialog ────────────────────────────────────────────────────────────
function ConfirmDialog({
  trigger,
  title,
  description,
  confirmLabel = "Confirm",
  destructive = false,
  onConfirm,
}: {
  trigger: React.ReactNode;
  title: string;
  description: string;
  confirmLabel?: string;
  destructive?: boolean;
  onConfirm: () => void;
}) {
  const [open, setOpen] = useState(false);
  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>{trigger}</DialogTrigger>
      <DialogContent className="max-w-sm">
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          <DialogDescription>{description}</DialogDescription>
        </DialogHeader>
        <DialogFooter className="gap-2">
          <Button variant="outline" size="sm" onClick={() => setOpen(false)}>
            Cancel
          </Button>
          <Button
            variant={destructive ? "destructive" : "default"}
            size="sm"
            onClick={() => {
              setOpen(false);
              onConfirm();
            }}
          >
            {confirmLabel}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// ── Per-persona card ──────────────────────────────────────────────────────────
type SaveState = "idle" | "editing" | "saving" | "saved" | "error";

function PersonaCard({
  persona,
  onSave,
  onDelete,
}: {
  persona: Persona;
  onSave: (p: Persona) => Promise<void>;
  onDelete: () => void;
}) {
  const [open, setOpen] = useState(false);
  const [draft, setDraft] = useState<Persona>(persona);
  const [state, setState] = useState<SaveState>("idle");
  const [errorMsg, setErrorMsg] = useState<string | null>(null);

  // Sync when parent updates (e.g. after reset)
  const prevId = useRef(persona.id);
  useEffect(() => {
    if (persona.id !== prevId.current || state === "idle") {
      setDraft(persona);
      prevId.current = persona.id;
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [persona]);

  const isDirty = JSON.stringify(draft) !== JSON.stringify(persona);

  function change(field: keyof Persona, value: string) {
    setDraft((d) => ({ ...d, [field]: value }));
    setState("editing");
  }

  async function save() {
    setState("saving");
    setErrorMsg(null);
    try {
      await onSave(draft);
      setState("saved");
      setTimeout(() => setState("idle"), 2500);
    } catch (e) {
      setErrorMsg((e as Error).message);
      setState("error");
    }
  }

  return (
    <div className="rounded-lg border bg-card">
      {/* Header row */}
      <div className="flex items-center gap-2 px-4 py-3">
        <button
          type="button"
          className="flex flex-1 items-center justify-between text-left text-sm font-medium"
          onClick={() => setOpen((o) => !o)}
        >
          <span className={draft.name ? "" : "italic text-muted-foreground"}>
            {draft.name || "Unnamed"}
          </span>
          {open ? (
            <ChevronUp className="h-4 w-4 shrink-0" />
          ) : (
            <ChevronDown className="h-4 w-4 shrink-0" />
          )}
        </button>

        <ConfirmDialog
          trigger={
            <Button variant="ghost" size="icon" className="h-7 w-7 text-muted-foreground hover:text-destructive">
              <Trash2 className="h-3.5 w-3.5" />
            </Button>
          }
          title="Delete persona"
          description={`Remove "${draft.name || "this persona"}" permanently? Students will no longer see it.`}
          confirmLabel="Delete"
          destructive
          onConfirm={onDelete}
        />
      </div>

      {/* Expandable fields */}
      {open && (
        <div className="space-y-3 border-t px-4 py-4">
          <div className="space-y-1">
            <Label>Name</Label>
            <Input
              value={draft.name}
              onChange={(e) => change("name", e.target.value)}
              placeholder="e.g. Socratic Tutor"
            />
          </div>
          <div className="space-y-1">
            <Label>Short description</Label>
            <Input
              value={draft.description}
              onChange={(e) => change("description", e.target.value)}
              placeholder="One sentence shown in the dropdown"
            />
          </div>
          <div className="space-y-1">
            <Label>System prompt</Label>
            <textarea
              className="min-h-[120px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
              value={draft.prompt}
              onChange={(e) => change("prompt", e.target.value)}
              placeholder="Instructions appended to the system message…"
            />
          </div>

          {errorMsg && <p className="text-xs text-destructive">{errorMsg}</p>}

          <Button
            size="sm"
            className="w-full"
            onClick={save}
            disabled={!isDirty || state === "saving"}
          >
            <Save className="mr-1 h-3.5 w-3.5" />
            {state === "saving"
              ? "Saving…"
              : state === "saved"
                ? "Saved!"
                : isDirty
                  ? "Save changes"
                  : "No changes"}
          </Button>
        </div>
      )}
    </div>
  );
}

// ── Main editor ───────────────────────────────────────────────────────────────
export function PersonaEditor() {
  const [personas, setPersonas] = useState<Persona[]>([]);

  async function load() {
    try {
      const r = await fetch("/api/personas");
      const d = await r.json();
      setPersonas(d.personas ?? []);
    } catch {}
  }

  useEffect(() => { load(); }, []);

  // Save a single updated persona
  async function saveOne(updated: Persona) {
    const next = personas.map((p) => (p.id === updated.id ? updated : p));
    const r = await fetch("/api/personas", {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(next),
    });
    if (!r.ok) throw new Error(await r.text());
    const data = await r.json();
    setPersonas(data.personas);
  }

  function remove(id: string) {
    const next = personas.filter((p) => p.id !== id);
    fetch("/api/personas", {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(next),
    })
      .then((r) => r.json())
      .then((d) => setPersonas(d.personas ?? next))
      .catch(() => setPersonas(next));
  }

  function addNew() {
    setPersonas((prev) => [
      ...prev,
      { id: uid(), name: "", description: "", prompt: "" },
    ]);
  }

  async function reset() {
    const r = await fetch("/api/personas/reset", { method: "POST" });
    if (!r.ok) throw new Error(await r.text());
    const data = await r.json();
    setPersonas(data.personas);
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <h2 className="text-sm font-semibold">Personas</h2>
        <ConfirmDialog
          trigger={
            <Button variant="ghost" size="sm" type="button">
              <RotateCcw className="mr-1 h-3.5 w-3.5" /> Reset to defaults
            </Button>
          }
          title="Reset personas?"
          description="All custom personas will be replaced with the bundled defaults. This cannot be undone."
          confirmLabel="Reset"
          destructive
          onConfirm={reset}
        />
      </div>
      <p className="text-xs text-muted-foreground">
        Each card saves individually. Changes are written to{" "}
        <code className="rounded bg-muted px-1">personas.json</code> and synced
        to your HF Dataset.
      </p>

      <div className="space-y-2">
        {personas.map((p) => (
          <PersonaCard
            key={p.id}
            persona={p}
            onSave={saveOne}
            onDelete={() => remove(p.id)}
          />
        ))}
      </div>

      <Button
        variant="outline"
        size="sm"
        type="button"
        className="w-full"
        onClick={addNew}
      >
        <Plus className="mr-1 h-4 w-4" /> Add persona
      </Button>
    </div>
  );
}
