import { useEffect, useMemo, useState } from "react";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Textarea } from "@/components/ui/textarea";
import {
  useAIPrompt,
  useAIPromptKeys,
  useAIPromptVersions,
  useActivateAIPrompt,
  useCreateAIPrompt,
  useRenderAIPrompt,
} from "@/hooks/queries/useAIPrompts";
import type { AIPromptSummary } from "@/types/ai-prompt";
import { CheckCircle2, FileText, History, Play, PlusCircle } from "lucide-react";
import { toast } from "sonner";

function SelectedKeyPanel({
  selectedKey,
  onSelectVersion,
  activePromptId,
}: {
  selectedKey: string;
  onSelectVersion: (id: number) => void;
  activePromptId: number | null;
}) {
  const { data, isLoading } = useAIPromptVersions(selectedKey);
  const activate = useActivateAIPrompt();

  if (isLoading) {
    return <Skeleton className="h-32 w-full" />;
  }
  const versions = data ?? [];
  if (!versions.length) {
    return (
      <p className="text-muted-foreground text-sm">
        No versions yet for this prompt.
      </p>
    );
  }

  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead>Version</TableHead>
          <TableHead>Title</TableHead>
          <TableHead>Author</TableHead>
          <TableHead>Status</TableHead>
          <TableHead className="text-right">Actions</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {versions.map((v) => (
          <TableRow
            key={v.id}
            className={activePromptId === v.id ? "bg-muted/50" : undefined}
          >
            <TableCell className="font-mono">v{v.version}</TableCell>
            <TableCell>{v.title}</TableCell>
            <TableCell>{v.author_name || "—"}</TableCell>
            <TableCell>
              {v.is_active ? (
                <Badge className="bg-emerald-500 text-white hover:bg-emerald-500">
                  Active
                </Badge>
              ) : (
                <Badge variant="secondary">Archived</Badge>
              )}
            </TableCell>
            <TableCell className="space-x-2 text-right">
              <Button
                size="sm"
                variant="outline"
                onClick={() => onSelectVersion(v.id)}
              >
                <FileText className="mr-1 h-3 w-3" />
                Open
              </Button>
              {!v.is_active ? (
                <Button
                  size="sm"
                  onClick={async () => {
                    try {
                      await activate.mutateAsync(v.id);
                      toast.success(`Activated v${v.version}`);
                    } catch (err) {
                      toast.error(
                        err instanceof Error ? err.message : "Activate failed",
                      );
                    }
                  }}
                  disabled={activate.isPending}
                >
                  <CheckCircle2 className="mr-1 h-3 w-3" />
                  Activate
                </Button>
              ) : null}
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}

function PromptDetail({ promptId }: { promptId: number }) {
  const { data, isLoading } = useAIPrompt(promptId);
  const render = useRenderAIPrompt();

  // Variables detected from the prompt body — keep local state keyed by name
  // so the editor can show one input per placeholder.
  const [sampleValues, setSampleValues] = useState<Record<string, string>>({});
  const [rendered, setRendered] = useState<string>("");

  useEffect(() => {
    setRendered("");
    setSampleValues({});
  }, [promptId]);

  if (isLoading || !data) {
    return <Skeleton className="h-40 w-full" />;
  }

  const variables = data.variables ?? [];

  return (
    <div className="space-y-4">
      <div>
        <h3 className="text-lg font-semibold">
          {data.title}{" "}
          <span className="text-muted-foreground font-normal">
            ({data.key} v{data.version})
          </span>
        </h3>
        {data.description ? (
          <p className="text-muted-foreground mt-1 text-sm">
            {data.description}
          </p>
        ) : null}
      </div>

      <div>
        <Label className="text-xs uppercase tracking-wide">Template</Label>
        <ScrollArea className="bg-muted/30 mt-1 max-h-64 rounded border">
          <pre className="p-3 font-mono text-sm whitespace-pre-wrap">
            {data.content}
          </pre>
        </ScrollArea>
      </div>

      {variables.length > 0 ? (
        <div className="space-y-2">
          <Label className="text-xs uppercase tracking-wide">
            Sample variables
          </Label>
          <div className="grid grid-cols-1 gap-2 md:grid-cols-2">
            {variables.map((v) => (
              <div key={v} className="space-y-1">
                <Label className="text-xs">{v}</Label>
                <Input
                  value={sampleValues[v] ?? ""}
                  onChange={(e) =>
                    setSampleValues((prev) => ({
                      ...prev,
                      [v]: e.target.value,
                    }))
                  }
                  placeholder={`Sample value for {${v}}`}
                />
              </div>
            ))}
          </div>
          <Button
            size="sm"
            variant="outline"
            onClick={async () => {
              try {
                const r = await render.mutateAsync({
                  id: data.id,
                  variables: sampleValues,
                });
                setRendered(r.rendered);
              } catch (err) {
                toast.error(
                  err instanceof Error ? err.message : "Render failed",
                );
              }
            }}
            disabled={render.isPending}
          >
            <Play className="mr-1 h-3 w-3" />
            Render preview
          </Button>
          {rendered ? (
            <ScrollArea className="bg-background mt-2 max-h-48 rounded border">
              <pre className="p-3 font-mono text-sm whitespace-pre-wrap">
                {rendered}
              </pre>
            </ScrollArea>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}

function NewVersionDialog({
  open,
  onOpenChange,
  defaultKey,
  defaultContent,
}: {
  open: boolean;
  onOpenChange: (v: boolean) => void;
  defaultKey: string;
  defaultContent: string;
}) {
  const create = useCreateAIPrompt();
  const [key, setKey] = useState(defaultKey);
  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [content, setContent] = useState(defaultContent);
  const [activate, setActivate] = useState(true);

  useEffect(() => {
    if (open) {
      setKey(defaultKey);
      setContent(defaultContent);
      setTitle("");
      setDescription("");
      setActivate(true);
    }
  }, [open, defaultKey, defaultContent]);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent
        className="max-w-2xl"
        description="Create a new prompt version; the previous active version will be archived."
      >
        <DialogHeader>
          <DialogTitle>New prompt version</DialogTitle>
        </DialogHeader>
        <div className="space-y-3">
          <div>
            <Label>Key</Label>
            <Input
              value={key}
              onChange={(e) => setKey(e.target.value.trim())}
              placeholder="exam.mcq.generate"
            />
            <p className="text-muted-foreground mt-1 text-xs">
              Lowercase dotted identifier. Reuse an existing key to bump its
              version.
            </p>
          </div>
          <div>
            <Label>Title</Label>
            <Input
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder="MCQ generation — CEFR B2 — v6"
            />
          </div>
          <div>
            <Label>Description (optional)</Label>
            <Textarea
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              rows={2}
              placeholder="What changed? What should editors know?"
            />
          </div>
          <div>
            <Label>Template</Label>
            <Textarea
              value={content}
              onChange={(e) => setContent(e.target.value)}
              rows={10}
              className="font-mono text-sm"
              placeholder="You are an exam author. Generate {count} MCQs for {topic}…"
            />
          </div>
          <label className="flex items-center gap-2 text-sm">
            <input
              type="checkbox"
              checked={activate}
              onChange={(e) => setActivate(e.target.checked)}
            />
            Activate this version immediately
          </label>
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            onClick={async () => {
              if (!key || !title || !content.trim()) {
                toast.error("Key, title, and content are required");
                return;
              }
              try {
                await create.mutateAsync({
                  key,
                  title,
                  description,
                  content,
                  activate,
                });
                toast.success("Prompt version created");
                onOpenChange(false);
              } catch (err) {
                toast.error(
                  err instanceof Error ? err.message : "Create failed",
                );
              }
            }}
            disabled={create.isPending}
          >
            Save version
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

export default function AIPromptEditor() {
  const [search, setSearch] = useState("");
  const { data, isLoading } = useAIPromptKeys({ search, page: 1, size: 50 });
  const [selectedKey, setSelectedKey] = useState<string | null>(null);
  const [selectedPromptId, setSelectedPromptId] = useState<number | null>(null);
  const [newOpen, setNewOpen] = useState(false);

  const items: AIPromptSummary[] = data?.items ?? [];
  const activePromptId = useMemo(() => {
    if (!selectedKey) return null;
    const match = items.find((it) => it.key === selectedKey);
    return match?.id ?? null;
  }, [items, selectedKey]);

  // Autoselect first key on load.
  useEffect(() => {
    if (!selectedKey && items.length) {
      setSelectedKey(items[0].key);
      setSelectedPromptId(items[0].id);
    }
  }, [items, selectedKey]);

  return (
    <div className="mx-auto max-w-7xl space-y-6 p-6">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <div>
          <h1 className="text-2xl font-semibold tracking-tight">
            AI prompt library
          </h1>
          <p className="text-muted-foreground mt-1 text-sm">
            Versioned, auditable templates that the AI pipelines render at
            runtime. Non-engineers can iterate here without shipping code.
          </p>
        </div>
        <Button onClick={() => setNewOpen(true)}>
          <PlusCircle className="mr-1 h-4 w-4" />
          New version
        </Button>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>Prompt keys</CardTitle>
          <CardDescription>
            Each row shows the latest version of a prompt key. Click a row to
            inspect all versions.
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-3">
          <Input
            placeholder="Search keys (e.g. exam.mcq)"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="max-w-sm"
          />
          {isLoading ? (
            <Skeleton className="h-32 w-full" />
          ) : items.length === 0 ? (
            <p className="text-muted-foreground text-sm">
              No prompts yet. Click <strong>New version</strong> to add one.
            </p>
          ) : (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Key</TableHead>
                  <TableHead>Latest</TableHead>
                  <TableHead>Title</TableHead>
                  <TableHead>Variables</TableHead>
                  <TableHead>Status</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {items.map((p) => (
                  <TableRow
                    key={p.id}
                    className={
                      selectedKey === p.key
                        ? "bg-muted/40 cursor-pointer"
                        : "cursor-pointer"
                    }
                    onClick={() => {
                      setSelectedKey(p.key);
                      setSelectedPromptId(p.id);
                    }}
                  >
                    <TableCell className="font-mono text-xs">{p.key}</TableCell>
                    <TableCell>
                      v{p.version}{" "}
                      {p.total_versions && p.total_versions > 1 ? (
                        <span className="text-muted-foreground text-xs">
                          (of {p.total_versions})
                        </span>
                      ) : null}
                    </TableCell>
                    <TableCell>{p.title}</TableCell>
                    <TableCell>
                      <div className="flex flex-wrap gap-1">
                        {p.variables.slice(0, 4).map((v) => (
                          <Badge key={v} variant="outline" className="text-xs">
                            {v}
                          </Badge>
                        ))}
                        {p.variables.length > 4 ? (
                          <Badge variant="outline" className="text-xs">
                            +{p.variables.length - 4}
                          </Badge>
                        ) : null}
                      </div>
                    </TableCell>
                    <TableCell>
                      {p.is_active ? (
                        <Badge className="bg-emerald-500 text-white hover:bg-emerald-500">
                          Active
                        </Badge>
                      ) : (
                        <Badge variant="secondary">No active</Badge>
                      )}
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          )}
        </CardContent>
      </Card>

      {selectedKey ? (
        <div className="grid gap-6 lg:grid-cols-2">
          <Card>
            <CardHeader>
              <CardTitle>
                <History className="mr-1 inline h-4 w-4" />
                Versions of {selectedKey}
              </CardTitle>
            </CardHeader>
            <CardContent>
              <SelectedKeyPanel
                selectedKey={selectedKey}
                onSelectVersion={setSelectedPromptId}
                activePromptId={selectedPromptId}
              />
            </CardContent>
          </Card>
          <Card>
            <CardHeader>
              <CardTitle>Preview</CardTitle>
              <CardDescription>
                Inspect template body and try a dry-run render.
              </CardDescription>
            </CardHeader>
            <CardContent>
              {selectedPromptId ? (
                <PromptDetail promptId={selectedPromptId} />
              ) : (
                <p className="text-muted-foreground text-sm">
                  Select a version from the list.
                </p>
              )}
            </CardContent>
          </Card>
        </div>
      ) : null}

      <NewVersionDialog
        open={newOpen}
        onOpenChange={setNewOpen}
        defaultKey={selectedKey ?? ""}
        defaultContent=""
      />
    </div>
  );
}
