"use client";

import { useId, useState, type ReactNode } from "react";
import { ChevronDownIcon, DownloadIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { Skeleton } from "@/components/ui/skeleton";
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { addDays } from "@/lib/format";
import { cn } from "@/lib/utils";

/* ------------------------------------------------------ Report filter bar */

const PRESETS = [
  { id: "today", label: "Today", back: 0 },
  { id: "7d", label: "7 days", back: 6 },
  { id: "30d", label: "30 days", back: 29 },
  { id: "90d", label: "90 days", back: 89 },
] as const;

export type ReportFilters = { from: string; to: string; branch: string };

export function ReportFilterBar({
  today,
  branches,
  exporting = null,
  disabled,
  onChange,
  onExport,
}: {
  today: string;
  branches: { id: number; name: string }[];
  /** Which export is running, if any. */
  exporting?: "excel" | "pdf" | "csv" | null;
  disabled?: boolean;
  onChange?: (f: ReportFilters) => void;
  onExport?: (kind: "excel" | "pdf" | "csv") => void;
}) {
  const uid = useId();
  const [preset, setPreset] = useState<string>("30d");
  const [from, setFrom] = useState(addDays(today, -29));
  const [to, setTo] = useState(today);
  const [branch, setBranch] = useState("all");
  const update = (next: Partial<ReportFilters>) =>
    onChange?.({ from, to, branch, ...next });
  return (
    <div className="flex flex-wrap items-end gap-3 rounded-lg border border-border bg-card p-3">
      <div className="space-y-1.5">
        <span className="text-xs font-medium text-muted-foreground">Period</span>
        <div role="group" aria-label="Date presets" className="flex overflow-hidden rounded-md border border-border bg-card">
          {PRESETS.map((p) => (
            <button
              key={p.id}
              type="button"
              disabled={disabled}
              aria-pressed={preset === p.id}
              onClick={() => {
                const f = addDays(today, -p.back);
                setPreset(p.id);
                setFrom(f);
                setTo(today);
                update({ from: f, to: today });
              }}
              className={cn(
                "h-8 cursor-pointer border-r border-border px-2.5 text-xs outline-none last:border-r-0 focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
                preset === p.id ? "bg-accent font-medium text-accent-foreground" : "bg-card text-muted-foreground hover:bg-muted",
              )}
            >
              {p.label}
            </button>
          ))}
        </div>
      </div>
      <div className="space-y-1.5">
        <Label htmlFor={`${uid}-from`} className="text-xs text-muted-foreground">
          From
        </Label>
        <Input id={`${uid}-from`} type="date" className="w-36" value={from} max={to} disabled={disabled} onChange={(e) => { setFrom(e.target.value); setPreset("custom"); update({ from: e.target.value }); }} />
      </div>
      <div className="space-y-1.5">
        <Label htmlFor={`${uid}-to`} className="text-xs text-muted-foreground">
          To
        </Label>
        <Input id={`${uid}-to`} type="date" className="w-36" value={to} min={from} max={today} disabled={disabled} onChange={(e) => { setTo(e.target.value); setPreset("custom"); update({ to: e.target.value }); }} />
      </div>
      <div className="space-y-1.5">
        <Label htmlFor={`${uid}-branch`} className="text-xs text-muted-foreground">
          Branch
        </Label>
        <NativeSelect id={`${uid}-branch`} className="w-44" value={branch} disabled={disabled} onChange={(e) => { setBranch(e.target.value); update({ branch: e.target.value }); }}>
          <NativeSelectOption value="all">All branches</NativeSelectOption>
          {branches.map((b) => (
            <NativeSelectOption key={b.id} value={String(b.id)}>
              {b.name}
            </NativeSelectOption>
          ))}
        </NativeSelect>
      </div>
      {/* R8 (card 037): one Export menu instead of three buttons */}
      {onExport ? (
        <div className="ml-auto">
          <DropdownMenu>
            <DropdownMenuTrigger render={<Button variant="outline" size="sm" disabled={disabled || exporting !== null} />}>
              <DownloadIcon data-icon="inline-start" />
              {exporting ? "Exporting…" : "Export"}
              <ChevronDownIcon data-icon="inline-end" />
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              {(["excel", "pdf", "csv"] as const).map((k) => (
                <DropdownMenuItem key={k} onClick={() => onExport(k)}>
                  {k === "excel" ? "Excel" : k === "pdf" ? "PDF" : "CSV"}
                </DropdownMenuItem>
              ))}
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      ) : null}
    </div>
  );
}

/* ----------------------------------------------------------- Report table */

export type ReportColumn<T> = {
  key: string;
  header: string;
  /** Numeric and money columns right-align. */
  numeric?: boolean;
  cell: (row: T) => ReactNode;
  /** Footer cell. Omit for blank. */
  total?: ReactNode;
};

export function ReportTable<T>({
  columns,
  rows,
  rowKey,
  state = "ready",
  error,
  emptyMessage = "No records in this period.",
  totalsLabel = "Total",
}: {
  columns: ReportColumn<T>[];
  rows: T[];
  rowKey: (row: T) => string | number;
  state?: "ready" | "loading" | "error";
  error?: string;
  emptyMessage?: string;
  totalsLabel?: string;
}) {
  const hasTotals = columns.some((c) => c.total !== undefined);
  const message = state === "error" ? (error ?? "The report could not be loaded.") : emptyMessage;
  return (
    <div className="overflow-hidden rounded-lg border border-border bg-card">
      <Table>
        <TableHeader>
          <TableRow>
            {columns.map((c) => (
              <TableHead key={c.key} className={c.numeric ? "text-right" : ""}>
                {c.header}
              </TableHead>
            ))}
          </TableRow>
        </TableHeader>
        <TableBody>
          {state === "loading"
            ? Array.from({ length: 4 }, (_, i) => (
                <TableRow key={i} aria-busy>
                  {columns.map((c) => (
                    <TableCell key={c.key}>
                      <Skeleton className={cn("h-4", c.numeric ? "ml-auto w-16" : "w-28")} />
                    </TableCell>
                  ))}
                </TableRow>
              ))
            : null}
          {state !== "loading" && (state === "error" || rows.length === 0) ? (
            <TableRow>
              <TableCell colSpan={columns.length} className={cn("py-8 text-center", state === "error" ? "text-status-error-text" : "text-muted-foreground")}>
                {message}
              </TableCell>
            </TableRow>
          ) : null}
          {state === "ready"
            ? rows.map((r) => (
                <TableRow key={rowKey(r)}>
                  {columns.map((c) => (
                    <TableCell key={c.key} className={c.numeric ? "text-right tabular-nums" : ""}>
                      {c.cell(r)}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            : null}
        </TableBody>
        {hasTotals && state === "ready" && rows.length > 0 ? (
          <TableFooter>
            <TableRow>
              {columns.map((c, i) => (
                <TableCell key={c.key} className={cn("font-semibold", c.numeric ? "text-right tabular-nums" : "")}>
                  {c.total ?? (i === 0 ? totalsLabel : "")}
                </TableCell>
              ))}
            </TableRow>
          </TableFooter>
        ) : null}
      </Table>
    </div>
  );
}

/* -------------------------------------------------------------- Chart card */

export type LegendItem = { label: string; color: string };

export function ChartCard({
  title,
  description,
  legend,
  state = "ready",
  error,
  emptyMessage = "No data for this period.",
  height = "h-56",
  children,
}: {
  title: string;
  description?: string;
  legend?: LegendItem[];
  state?: "ready" | "loading" | "empty" | "error";
  error?: string;
  emptyMessage?: string;
  height?: string;
  children?: ReactNode;
}) {
  return (
    <div className="rounded-lg border border-border bg-card">
      <div className="flex flex-wrap items-start justify-between gap-2 border-b border-border px-3 py-2">
        <div>
          <h3 className="text-sm font-semibold text-foreground">{title}</h3>
          {description ? <p className="text-xs text-muted-foreground">{description}</p> : null}
        </div>
        {legend && state === "ready" ? (
          <ul className="flex flex-wrap gap-3 text-xs text-muted-foreground">
            {legend.map((l) => (
              <li key={l.label} className="flex items-center gap-1.5">
                <span className="size-2 rounded-[2px]" style={{ backgroundColor: l.color }} aria-hidden />
                {l.label}
              </li>
            ))}
          </ul>
        ) : null}
      </div>
      <div className={cn("p-3", height)}>
        {state === "loading" ? (
          <Skeleton className="h-full w-full" aria-busy />
        ) : state === "empty" ? (
          <div className="flex h-full items-center justify-center text-sm text-muted-foreground">{emptyMessage}</div>
        ) : state === "error" ? (
          <div role="alert" className="flex h-full items-center justify-center text-sm text-status-error-text">
            {error ?? "The chart could not be loaded."}
          </div>
        ) : (
          children
        )}
      </div>
    </div>
  );
}
