import { useState, useRef, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Separator } from "@/components/ui/separator";
import { Card, CardContent } from "@/components/ui/card";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Plus, Trash2, Printer, Eye, X, Save, FolderOpen, GripVertical, ChevronDown } from "lucide-react";
import { useToast } from "@/components/ui/use-toast";
import { DragDropContext, Droppable, Draggable, DropResult } from "@hello-pangea/dnd";

interface Candidate {
  id: string;
  name: string;
}

interface SavedBallot {
  id: string;
  name: string;
  savedAt: string;
  data: {
    associationName: string;
    electionDate: string;
    seatsAvailable: number;
    termLength: string;
    instructions: string;
    candidates: Candidate[];
  };
}

const STORAGE_KEY = "saved_ballots";

function getSavedBallots(): SavedBallot[] {
  try {
    return JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]");
  } catch {
    return [];
  }
}

function saveBallots(ballots: SavedBallot[]) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(ballots));
}

// Strict-mode safe droppable wrapper
function StrictModeDroppable({ children, ...props }: any) {
  const [enabled, setEnabled] = useState(false);
  useState(() => {
    const animation = requestAnimationFrame(() => setEnabled(true));
    return () => cancelAnimationFrame(animation);
  });
  if (!enabled) return null;
  return <Droppable {...props}>{children}</Droppable>;
}

export default function BallotForm() {
  const { toast } = useToast();
  const [associationName, setAssociationName] = useState("");
  const [electionDate, setElectionDate] = useState("");
  const [seatsAvailable, setSeatsAvailable] = useState(1);
  const [termLength, setTermLength] = useState("1 year");
  const [instructions, setInstructions] = useState(
    "After completing the ballot, place your vote in the ballot box."
  );
  const [candidates, setCandidates] = useState<Candidate[]>([
    { id: crypto.randomUUID(), name: "" },
  ]);
  const [showPreview, setShowPreview] = useState(false);
  const [savedBallots, setSavedBallots] = useState<SavedBallot[]>(getSavedBallots);
  const printRef = useRef<HTMLDivElement>(null);

  const addCandidate = () => {
    setCandidates((prev) => [...prev, { id: crypto.randomUUID(), name: "" }]);
  };

  const removeCandidate = (id: string) => {
    setCandidates((prev) => prev.filter((c) => c.id !== id));
  };

  const updateCandidate = (id: string, name: string) => {
    setCandidates((prev) => prev.map((c) => (c.id === id ? { ...c, name } : c)));
  };

  const onDragEnd = useCallback((result: DropResult) => {
    if (!result.destination) return;
    setCandidates((prev) => {
      const items = Array.from(prev);
      const [moved] = items.splice(result.source.index, 1);
      items.splice(result.destination!.index, 0, moved);
      return items;
    });
  }, []);

  const filledCandidates = candidates.filter((c) => c.name.trim());

  // Save ballot
  const handleSave = () => {
    if (!associationName.trim()) {
      toast({ variant: "destructive", title: "Missing name", description: "Enter an association name before saving." });
      return;
    }
    const ballotName = `${associationName} — ${electionDate || "No date"}`;
    const existing = getSavedBallots();
    const newBallot: SavedBallot = {
      id: crypto.randomUUID(),
      name: ballotName,
      savedAt: new Date().toISOString(),
      data: { associationName, electionDate, seatsAvailable, termLength, instructions, candidates },
    };
    const updated = [newBallot, ...existing].slice(0, 20); // keep max 20
    saveBallots(updated);
    setSavedBallots(updated);
    toast({ title: "Ballot Saved", description: `"${ballotName}" saved successfully.` });
  };

  // Load ballot
  const handleLoad = (ballot: SavedBallot) => {
    const d = ballot.data;
    setAssociationName(d.associationName);
    setElectionDate(d.electionDate);
    setSeatsAvailable(d.seatsAvailable);
    setTermLength(d.termLength);
    setInstructions(d.instructions);
    setCandidates(d.candidates.length > 0 ? d.candidates : [{ id: crypto.randomUUID(), name: "" }]);
    toast({ title: "Ballot Loaded", description: `"${ballot.name}" loaded.` });
  };

  // Delete saved ballot
  const handleDeleteSaved = (id: string, e: React.MouseEvent) => {
    e.stopPropagation();
    const updated = getSavedBallots().filter((b) => b.id !== id);
    saveBallots(updated);
    setSavedBallots(updated);
    toast({ title: "Deleted", description: "Saved ballot removed." });
  };

  const seatsWord = (n: number) => {
    const words = ["zero","one","two","three","four","five","six","seven","eight","nine","ten"];
    return words[n] || String(n);
  };

  const formattedDate = electionDate
    ? new Date(electionDate + "T00:00:00").toLocaleDateString("en-US", {
        year: "numeric", month: "long", day: "numeric",
      })
    : "";

  const handlePrint = () => {
    if (!associationName || filledCandidates.length === 0) {
      toast({ variant: "destructive", title: "Missing information", description: "Please enter an association name and at least one candidate." });
      return;
    }
    setShowPreview(true);
    setTimeout(() => {
      const content = printRef.current;
      if (!content) return;
      const win = window.open("", "_blank");
      if (!win) return;
      win.document.write(`<!DOCTYPE html><html><head><title>Official Ballot</title>
        <style>
          @media print { @page { size: letter; margin: 0.75in; } body { margin: 0; } }
          * { box-sizing: border-box; margin: 0; padding: 0; }
          body { font-family: 'Times New Roman', Georgia, serif; color: #1a1a1a; }
        </style></head><body>${content.innerHTML}</body></html>`);
      win.document.close();
      win.focus();
      win.print();
      win.close();
    }, 300);
  };

  // --- Preview / Print ballot markup ---
  const BallotPreview = () => (
    <div
      ref={printRef}
      style={{
        position: "relative", width: "7in", minHeight: "9.5in", margin: "0 auto",
        padding: "0.6in 0.75in", fontFamily: "'Times New Roman', Georgia, serif",
        color: "#1a1a1a", background: "#fff", overflow: "hidden",
      }}
    >
      {/* OFFICIAL watermark */}
      <div style={{
        position: "absolute", top: "50%", left: "50%",
        transform: "translate(-50%, -50%) rotate(-35deg)", fontSize: "120px",
        fontWeight: 700, letterSpacing: "18px", color: "rgba(0, 0, 0, 0.04)",
        whiteSpace: "nowrap", pointerEvents: "none", userSelect: "none", zIndex: 0,
        textTransform: "uppercase", fontFamily: "'Times New Roman', Georgia, serif",
      }}>
        OFFICIAL
      </div>

      <div style={{ position: "relative", zIndex: 1, display: "flex", flexDirection: "column", minHeight: "calc(100% - 40px)" }}>
        <div style={{ textAlign: "center", marginBottom: "18px" }}>
          <div style={{
            display: "inline-block", background: "#1e3a5f", color: "#fff",
            padding: "6px 32px", fontSize: "13px", fontWeight: 700,
            letterSpacing: "3px", textTransform: "uppercase", marginBottom: "10px",
          }}>
            Official Ballot
          </div>
        </div>

        <h1 style={{ textAlign: "center", fontSize: "20px", fontWeight: 700, margin: "0 0 6px", lineHeight: 1.3 }}>
          {associationName || "Association Name"}
        </h1>

        {formattedDate && (
          <p style={{ textAlign: "center", fontSize: "13px", margin: "0 0 20px", color: "#555" }}>
            {formattedDate}
          </p>
        )}

        <Separator style={{ margin: "0 0 18px", borderColor: "#1e3a5f" }} />

        <p style={{ fontSize: "13px", lineHeight: 1.7, marginBottom: "10px", textAlign: "justify" }}>
          The following candidates are for election to the Board of Directors of{" "}
          <strong>{associationName || "the Association"}</strong>. There{" "}
          {seatsAvailable === 1 ? "is" : "are"} currently{" "}
          <strong>{seatsWord(seatsAvailable)} ({seatsAvailable})</strong>{" "}
          position{seatsAvailable !== 1 ? "s" : ""} open on the Board of Directors for a term of{" "}
          <strong>{termLength}</strong>.
        </p>

        <p style={{ fontSize: "13px", lineHeight: 1.7, marginBottom: "24px", textAlign: "justify" }}>
          Place a checkmark (✓) next to the candidate of your choice. Please select{" "}
          <strong>{seatsWord(seatsAvailable).toUpperCase()}</strong> candidate
          {seatsAvailable !== 1 ? "s" : ""}. Any ballot that casts more than{" "}
          {seatsWord(seatsAvailable)} vote{seatsAvailable !== 1 ? "s" : ""} will be deemed invalid.
        </p>

        <div style={{ marginBottom: "28px", paddingLeft: "12px", flex: "0 0 auto" }}>
          {filledCandidates.map((c) => (
            <div key={c.id} style={{
              display: "flex", alignItems: "center", gap: "12px",
              padding: "7px 0", borderBottom: "1px solid #e5e5e5", fontSize: "14px",
            }}>
              <span style={{
                display: "inline-block", width: "16px", height: "16px",
                border: "1.5px solid #333", borderRadius: "2px", flexShrink: 0,
              }} />
              <span>{c.name}</span>
            </div>
          ))}
        </div>

        {instructions && (
          <div style={{
            background: "#f5f5f0", border: "1px solid #ddd", borderRadius: "4px",
            padding: "14px 18px", marginTop: "auto",
          }}>
            <h3 style={{ fontSize: "13px", fontWeight: 700, marginBottom: "6px", textTransform: "uppercase", letterSpacing: "1px" }}>
              Instructions
            </h3>
            <p style={{ fontSize: "12.5px", lineHeight: 1.6 }}>{instructions}</p>
          </div>
        )}
      </div>
    </div>
  );

  return (
    <div className="p-6 max-w-5xl mx-auto space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-xl font-bold text-foreground">Ballot Generator</h1>
          <p className="text-xs text-muted-foreground mt-0.5">
            Create official election ballots with candidates and print-ready output
          </p>
        </div>
        <div className="flex gap-2">
          <Button variant="outline" size="sm" className="gap-1.5 text-xs" onClick={handleSave}>
            <Save className="h-3.5 w-3.5" /> Save
          </Button>

          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="outline" size="sm" className="gap-1.5 text-xs">
                <FolderOpen className="h-3.5 w-3.5" /> Load <ChevronDown className="h-3 w-3 ml-0.5" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-72 max-h-64 overflow-y-auto">
              {savedBallots.length === 0 ? (
                <DropdownMenuItem disabled className="text-xs text-muted-foreground">
                  No saved ballots
                </DropdownMenuItem>
              ) : (
                savedBallots.map((b) => (
                  <DropdownMenuItem key={b.id} onClick={() => handleLoad(b)} className="flex items-center justify-between text-xs group">
                    <div className="flex-1 min-w-0">
                      <p className="truncate font-medium">{b.name}</p>
                      <p className="text-[10px] text-muted-foreground">
                        {new Date(b.savedAt).toLocaleDateString()}
                      </p>
                    </div>
                    <Button
                      variant="ghost"
                      size="icon"
                      className="h-6 w-6 opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-destructive shrink-0"
                      onClick={(e) => handleDeleteSaved(b.id, e)}
                    >
                      <Trash2 className="h-3 w-3" />
                    </Button>
                  </DropdownMenuItem>
                ))
              )}
            </DropdownMenuContent>
          </DropdownMenu>

          <Button
            variant="outline" size="sm" className="gap-1.5 text-xs"
            onClick={() => {
              if (!associationName || filledCandidates.length === 0) {
                toast({ variant: "destructive", title: "Missing info", description: "Enter association name and at least one candidate." });
                return;
              }
              setShowPreview(true);
            }}
          >
            <Eye className="h-3.5 w-3.5" /> Preview
          </Button>
          <Button size="sm" className="gap-1.5 text-xs" onClick={handlePrint}>
            <Printer className="h-3.5 w-3.5" /> Print Ballot
          </Button>
        </div>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        {/* Left: Details */}
        <Card>
          <CardContent className="p-5 space-y-4">
            <h2 className="text-sm font-semibold text-foreground">Election Details</h2>
            <div className="space-y-1.5">
              <Label className="text-xs">Association / Community Name</Label>
              <Input placeholder="e.g. Bridgewater at Bayside Lakes HOA, Inc." value={associationName} onChange={(e) => setAssociationName(e.target.value)} className="h-9 text-sm" />
            </div>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-1.5">
                <Label className="text-xs">Election Date</Label>
                <Input type="date" value={electionDate} onChange={(e) => setElectionDate(e.target.value)} className="h-9 text-sm" />
              </div>
              <div className="space-y-1.5">
                <Label className="text-xs">Open Seats</Label>
                <Input type="number" min={1} max={20} value={seatsAvailable} onChange={(e) => setSeatsAvailable(Number(e.target.value))} className="h-9 text-sm" />
              </div>
            </div>
            <div className="space-y-1.5">
              <Label className="text-xs">Term Length</Label>
              <Input placeholder="e.g. 1 year, 2 years" value={termLength} onChange={(e) => setTermLength(e.target.value)} className="h-9 text-sm" />
            </div>
            <div className="space-y-1.5">
              <Label className="text-xs">Voting Instructions</Label>
              <Textarea value={instructions} onChange={(e) => setInstructions(e.target.value)} rows={2} className="text-sm" />
            </div>
          </CardContent>
        </Card>

        {/* Right: Candidates with drag-and-drop */}
        <Card>
          <CardContent className="p-5 space-y-4">
            <div className="flex items-center justify-between">
              <h2 className="text-sm font-semibold text-foreground">Candidates ({candidates.length})</h2>
              <Button variant="outline" size="sm" className="gap-1.5 text-xs" onClick={addCandidate}>
                <Plus className="h-3.5 w-3.5" /> Add Candidate
              </Button>
            </div>

            <DragDropContext onDragEnd={onDragEnd}>
              <StrictModeDroppable droppableId="candidates">
                {(provided: any) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.droppableProps}
                    className="space-y-2 max-h-[400px] overflow-y-auto pr-1"
                  >
                    {candidates.map((c, idx) => (
                      <Draggable key={c.id} draggableId={c.id} index={idx}>
                        {(provided: any, snapshot: any) => (
                          <div
                            ref={provided.innerRef}
                            {...provided.draggableProps}
                            className={`flex items-center gap-2 ${snapshot.isDragging ? "bg-accent/50 rounded shadow-sm" : ""}`}
                          >
                            <div {...provided.dragHandleProps} className="cursor-grab active:cursor-grabbing text-muted-foreground hover:text-foreground shrink-0">
                              <GripVertical className="h-4 w-4" />
                            </div>
                            <span className="text-xs text-muted-foreground w-5 text-right shrink-0">
                              {idx + 1}.
                            </span>
                            <Input
                              placeholder="Last Name, First Name"
                              value={c.name}
                              onChange={(e) => updateCandidate(c.id, e.target.value)}
                              className="h-9 text-sm flex-1"
                            />
                            <Button
                              variant="ghost" size="icon"
                              className="h-8 w-8 text-muted-foreground hover:text-destructive"
                              onClick={() => removeCandidate(c.id)}
                              disabled={candidates.length <= 1}
                            >
                              <Trash2 className="h-3.5 w-3.5" />
                            </Button>
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </StrictModeDroppable>
            </DragDropContext>
          </CardContent>
        </Card>
      </div>

      {/* Live mini preview */}
      <Card className="overflow-hidden">
        <CardContent className="p-0">
          <div className="bg-muted/30 px-5 py-3 border-b border-border flex items-center justify-between">
            <span className="text-xs font-medium text-muted-foreground">Live Preview</span>
          </div>
          <div className="bg-white p-6 flex justify-center overflow-auto">
            <div style={{ transform: "scale(0.65)", transformOrigin: "top center" }}>
              <BallotPreview />
            </div>
          </div>
        </CardContent>
      </Card>

      {/* Full-screen preview modal */}
      {showPreview && (
        <div className="fixed inset-0 z-50 bg-black/60 flex items-start justify-center overflow-auto py-10">
          <div className="bg-white rounded-lg shadow-2xl max-w-[8in] w-full relative">
            <div className="sticky top-0 z-10 bg-white border-b flex items-center justify-between px-5 py-3 rounded-t-lg">
              <span className="text-sm font-semibold">Ballot Preview</span>
              <div className="flex gap-2">
                <Button size="sm" className="gap-1.5 text-xs" onClick={handlePrint}>
                  <Printer className="h-3.5 w-3.5" /> Print
                </Button>
                <Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => setShowPreview(false)}>
                  <X className="h-4 w-4" />
                </Button>
              </div>
            </div>
            <div className="p-4">
              <BallotPreview />
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
