"use client";

import { useState } from "react";
import { toast } from "sonner";
import { Check, Copy, FileText, Loader2, Sparkles } from "lucide-react";

import { colorModeFromTheme } from "@/components/theme/use-dark-theme";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Popover,
  PopoverContent,
  PopoverDescription,
  PopoverHeader,
  PopoverTitle,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { MarkdownPreview } from "@/components/markdown/markdown-widgets";
import { summarizeBoard } from "@/lib/actions/summarize";
import { toDateKey } from "@/lib/dates";

const DATE_RANGE_OPTIONS = [
  { value: "today", label: "Today" },
  { value: "thisWeek", label: "This Week" },
  { value: "thisMonth", label: "This Month" },
  { value: "lastMonth", label: "Last Month" },
  { value: "custom", label: "Custom Range" },
] as const;

const ORGANIZE_BY_OPTIONS = [
  { value: "byDate", label: "By Date" },
  { value: "byCategory", label: "By Category/Group" },
] as const;

type DateRange = (typeof DATE_RANGE_OPTIONS)[number]["value"];
type OrganizeBy = (typeof ORGANIZE_BY_OPTIONS)[number]["value"];

/**
 * Board header's "Summary" button: a compact popover with two dropdowns
 * (date range + how to organize) and a Summarize action, then a
 * result dialog that renders the AI's markdown recap with a copy-to-
 * clipboard icon. Scoped to whatever board it's mounted on (Home or a
 * Project) via `projectId`.
 */
export function SummaryButton({ projectId }: { projectId?: string }) {
  const colorMode = colorModeFromTheme();

  // Popover (selection) state.
  const [popoverOpen, setPopoverOpen] = useState(false);
  const [dateRange, setDateRange] = useState<DateRange>("today");
  const [organizeBy, setOrganizeBy] = useState<OrganizeBy>("byDate");
  // Both default to today so a "Custom Range" pick is immediately usable.
  const [customStart, setCustomStart] = useState(() => toDateKey(new Date()));
  const [customEnd, setCustomEnd] = useState(() => toDateKey(new Date()));

  // Result dialog state.
  const [resultOpen, setResultOpen] = useState(false);
  const [generating, setGenerating] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [noWork, setNoWork] = useState(false);
  const [summary, setSummary] = useState<string | null>(null);
  const [rangeLabel, setRangeLabel] = useState<string | null>(null);
  const [count, setCount] = useState(0);
  const [copied, setCopied] = useState(false);

  const customInvalid =
    dateRange === "custom" && (!customStart || !customEnd || customStart > customEnd);

  async function handleSummarize() {
    if (generating || customInvalid) return;
    setPopoverOpen(false);
    setResultOpen(true);
    setGenerating(true);
    setError(null);
    setNoWork(false);
    setSummary(null);
    setRangeLabel(null);
    setCount(0);
    setCopied(false);

    try {
      const result = await summarizeBoard(projectId ?? null, {
        dateRange,
        customStart: dateRange === "custom" ? customStart : undefined,
        customEnd: dateRange === "custom" ? customEnd : undefined,
        organizeBy,
      });

      if (result.status === "ok") {
        setSummary(result.content);
        setRangeLabel(result.rangeLabel);
        setCount(result.count);
      } else if (result.status === "empty") {
        setRangeLabel(result.rangeLabel);
        setNoWork(true);
      } else {
        throw new Error(result.error);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Something went wrong.");
    } finally {
      setGenerating(false);
    }
  }

  // Starts fresh every time it's reopened -- a summary from a different
  // range would be stale the moment the dialog closes and reopens.
  function handleResultOpenChange(next: boolean) {
    if (!next) {
      setGenerating(false);
      setError(null);
      setNoWork(false);
      setSummary(null);
      setRangeLabel(null);
      setCount(0);
      setCopied(false);
    }
    setResultOpen(next);
  }

  async function handleCopy() {
    if (!summary) return;
    try {
      await navigator.clipboard.writeText(summary);
      setCopied(true);
      toast.success("Summary copied to clipboard.");
      setTimeout(() => setCopied(false), 2000);
    } catch {
      toast.error("Couldn't copy to clipboard.");
    }
  }

  return (
    <>
      <Popover open={popoverOpen} onOpenChange={setPopoverOpen}>
        <PopoverTrigger
          render={
            <Button variant="outline" size="sm" className="gap-1.5" aria-label="Summarize completed work">
              <FileText className="size-3.5" />
              <span className="hidden md:inline">Summary</span>
            </Button>
          }
        />
        <PopoverContent align="end" className="w-72">
          <PopoverHeader>
            <PopoverTitle>Summarize completed work</PopoverTitle>
            <PopoverDescription>An AI recap of what you got done on this board.</PopoverDescription>
          </PopoverHeader>

          <div className="space-y-3.5">
            <div className="space-y-1.5">
              <Label htmlFor="summary-date-range">Date range</Label>
              <Select
                value={dateRange}
                // Without `items`, <Select.Value> can't look up a label for
                // the current value until the popup has opened once.
                items={DATE_RANGE_OPTIONS}
                onValueChange={(v) => v && setDateRange(v as DateRange)}
              >
                <SelectTrigger id="summary-date-range" className="w-full">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {DATE_RANGE_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            {dateRange === "custom" && (
              <div className="grid grid-cols-2 gap-2">
                <div className="space-y-1.5">
                  <Label htmlFor="summary-custom-start">Start</Label>
                  <Input
                    id="summary-custom-start"
                    type="date"
                    value={customStart}
                    max={customEnd || undefined}
                    onChange={(e) => setCustomStart(e.target.value)}
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="summary-custom-end">End</Label>
                  <Input
                    id="summary-custom-end"
                    type="date"
                    value={customEnd}
                    min={customStart || undefined}
                    onChange={(e) => setCustomEnd(e.target.value)}
                  />
                </div>
              </div>
            )}

            <div className="space-y-1.5">
              <Label htmlFor="summary-organize-by">Organize by</Label>
              <Select
                value={organizeBy}
                items={ORGANIZE_BY_OPTIONS}
                onValueChange={(v) => v && setOrganizeBy(v as OrganizeBy)}
              >
                <SelectTrigger id="summary-organize-by" className="w-full">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {ORGANIZE_BY_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            {customInvalid && (
              <p className="text-xs text-destructive">
                Pick a start date on or before the end date.
              </p>
            )}

            <Button
              className="w-full gap-2"
              disabled={generating || customInvalid}
              onClick={handleSummarize}
            >
              {generating ? (
                <Loader2 className="size-4 animate-spin" />
              ) : (
                <Sparkles className="size-4" />
              )}
              Summarize
            </Button>
          </div>
        </PopoverContent>
      </Popover>

      <Dialog open={resultOpen} onOpenChange={handleResultOpenChange}>
        <DialogContent className="flex max-h-[80vh] flex-col sm:max-w-xl" data-color-mode={colorMode}>
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2">
              <Sparkles className="size-4 text-primary" />
              Summary
            </DialogTitle>
            <DialogDescription>
              {rangeLabel
                ? `${rangeLabel} · ${count} completed ${count === 1 ? "item" : "items"}`
                : "An AI recap of what you got done."}
            </DialogDescription>
          </DialogHeader>

          {generating && (
            <div className="flex flex-col items-center gap-3 rounded-md border border-dashed p-10">
              <Loader2 className="size-6 animate-spin text-muted-foreground" />
              <p className="text-sm text-muted-foreground">Summarizing your completed work…</p>
            </div>
          )}

          {!generating && error && (
            <div className="space-y-3">
              <p className="text-sm text-destructive">{error}</p>
              <div className="flex justify-end gap-2">
                <Button variant="outline" size="sm" onClick={() => setResultOpen(false)}>
                  Close
                </Button>
                <Button size="sm" onClick={handleSummarize}>
                  Try again
                </Button>
              </div>
            </div>
          )}

          {!generating && !error && noWork && (
            <p className="rounded-md border border-dashed p-8 text-center text-sm text-muted-foreground">
              Nothing was completed in this range yet -- check something off first.
            </p>
          )}

          {!generating && !error && !noWork && summary && (
            <div className="min-h-0 flex-1 overflow-y-auto rounded-md border p-4">
              <MarkdownPreview source={summary} />
            </div>
          )}

          {summary && (
            <div className="flex items-center justify-between gap-2">
              <Tooltip>
                <TooltipTrigger
                  render={
                    <Button
                      variant="ghost"
                      size="icon-sm"
                      aria-label={copied ? "Copied" : "Copy summary to clipboard"}
                      onClick={handleCopy}
                    >
                      {copied ? <Check className="size-4" /> : <Copy className="size-4" />}
                    </Button>
                  }
                />
                <TooltipContent side="top">{copied ? "Copied" : "Copy to clipboard"}</TooltipContent>
              </Tooltip>
              <Button variant="outline" size="sm" onClick={() => setResultOpen(false)}>
                Done
              </Button>
            </div>
          )}
        </DialogContent>
      </Dialog>
    </>
  );
}
