"use client";

import { toastApiError } from "@/lib/toast-api-error";
import * as React from "react";
import {
  BarChart3,
  ChevronLeft,
  ChevronRight,
  Database,
  Download,
  Pencil,
  Save,
  Search,
  User,
} from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogMedia,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";

import {
  compareBenchmark,
  loadBenchmarkSettings,
  populateBenchmarkData,
  saveBenchmarkAdminAlias,
  saveBenchmarkSettings,
} from "../_lib/tenant-settings-api";
import type { BenchmarkComparisonData, BenchmarkSettingsData } from "../_lib/tenant-settings-server-api";
import { formatPlainAmount } from "@/lib/format/numbers";

type FilterKey = "assetClass" | "assetType" | "banks" | "currency" | "industry" | "sector" | "geography";
type Filters = Record<FilterKey, string[]>;
const EMPTY_FILTERS: Filters = {
  assetClass: [], assetType: [], banks: [], currency: [], industry: [], sector: [], geography: [],
};

function exportRows(rows: BenchmarkComparisonData["comp_benchmark_rows"]) {
  if (!rows.length) return;
  const headers = Object.keys(rows[0]);
  const csv = [headers, ...rows.map((row) => headers.map((header) => row[header]))]
    .map((row) => row.map((cell) => `"${String(cell ?? "").replaceAll('"', '""')}"`).join(","))
    .join("\n");
  const url = URL.createObjectURL(new Blob([csv], { type: "text/csv;charset=utf-8" }));
  const anchor = document.createElement("a");
  anchor.href = url;
  anchor.download = "benchmark-comparison.csv";
  anchor.click();
  URL.revokeObjectURL(url);
}

function ComparisonChart({ data }: { data: BenchmarkComparisonData }) {
  const width = 900;
  const height = 260;
  const values = [...data.my_series, ...data.comp_series].filter((value): value is number => value !== null);
  const min = Math.min(...values, 0);
  const max = Math.max(...values, 1);
  const range = max - min || 1;
  const points = (series: Array<number | null>) => series
    .map((value, index) => value === null ? null : `${(index / Math.max(1, series.length - 1)) * width},${height - ((value - min) / range) * height}`)
    .filter(Boolean)
    .join(" ");

  return (
    <div className="rounded-xl border bg-card p-4">
      <div className="mb-4 flex flex-wrap gap-5 text-sm">
        <span><i className="mr-2 inline-block size-2.5 rounded-full bg-blue-600" />{data.my_label}</span>
        <span><i className="mr-2 inline-block size-2.5 rounded-full bg-orange-500" />{data.comp_label}</span>
      </div>
      <div className="overflow-x-auto">
        <svg viewBox={`0 0 ${width} ${height}`} className="h-64 min-w-[700px] w-full" role="img" aria-label="Benchmark comparison chart">
          {[0, 0.25, 0.5, 0.75, 1].map((fraction) => (
            <line key={fraction} x1="0" x2={width} y1={height * fraction} y2={height * fraction} className="stroke-border" />
          ))}
          <polyline fill="none" stroke="#2563eb" strokeWidth="3" points={points(data.my_series)} />
          <polyline fill="none" stroke="#f97316" strokeWidth="3" points={points(data.comp_series)} />
        </svg>
      </div>
      <div className="mt-4 grid gap-3 sm:grid-cols-3">
        {[
          [data.my_label, data.my_stats],
          [data.comp_label, data.comp_stats],
          ["Alpha", { total_return: data.my_stats.total_return - data.comp_stats.total_return, high: 0, low: 0 }],
        ].map(([label, stats]) => {
          const values = stats as BenchmarkComparisonData["my_stats"];
          return (
            <div key={String(label)} className="rounded-lg bg-muted/50 p-3">
              <p className="text-muted-foreground text-xs">{String(label)}</p>
              <p className="mt-1 font-semibold text-lg">{values.total_return.toFixed(2)}%</p>
              {label !== "Alpha" && <p className="text-muted-foreground text-xs">High {values.high.toFixed(2)}% · Low {values.low.toFixed(2)}%</p>}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function AdminBenchmarkPanel({
  tenant,
  data,
  onRefresh,
}: {
  tenant: string;
  data: BenchmarkSettingsData;
  onRefresh: (next: BenchmarkSettingsData) => void;
}) {
  const [query, setQuery] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [populateOpen, setPopulateOpen] = React.useState(false);
  const [editCid, setEditCid] = React.useState<number | null>(null);
  const [editAlias, setEditAlias] = React.useState("");

  const customers = data.customerList ?? [];
  const enabledCount = customers.filter((row) => row.is_enabled).length;
  const filtered = customers.filter((row) => {
    const q = query.trim().toLowerCase();
    if (!q) return true;
    return `${row.name} ${row.alias_name ?? ""}`.toLowerCase().includes(q);
  });

  async function confirmPopulate() {
    setBusy(true);
    try {
      const result = await populateBenchmarkData(tenant);
      const inserted = result.total_inserted ?? 0;
      const count = result.customer_count ?? 0;
      const warnings = result.errors ?? [];
      if (warnings.length > 0) {
        toast.warning(
          `Populated ${formatPlainAmount(inserted)} rows for ${count} customer(s). ${warnings.length} warning(s).`,
        );
      } else {
        toast.success(`Populated ${formatPlainAmount(inserted)} rows for ${count} customer(s).`);
      }
      setPopulateOpen(false);
      const refreshed = await loadBenchmarkSettings(tenant);
      onRefresh(refreshed);
    } catch (error) {
      toastApiError(error, "Populate failed.");
    } finally {
      setBusy(false);
    }
  }

  async function saveAlias() {
    if (editCid === null || !editAlias.trim()) return;
    setBusy(true);
    try {
      const result = await saveBenchmarkAdminAlias(tenant, editCid, editAlias.trim());
      onRefresh(result);
      setEditCid(null);
      setEditAlias("");
      toast.success("Alias updated");
    } catch (error) {
      toastApiError(error, "Alias could not be saved.");
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="space-y-5">
      <div>
        <h2 className="font-semibold text-xl">Benchmark Settings</h2>
        <p className="text-muted-foreground text-sm">View benchmark status for all customers.</p>
      </div>

      <div className="relative max-w-xl">
        <Search className="pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" />
        <Input
          className="pl-9"
          value={query}
          onChange={(event) => setQuery(event.target.value)}
          placeholder="Search customers..."
        />
      </div>

      <div className="flex flex-wrap items-center gap-4 text-sm">
        <span className="text-muted-foreground"><strong className="text-foreground">{customers.length}</strong> total</span>
        <span className="text-emerald-600"><strong>{enabledCount}</strong> enabled</span>
        <span className="text-muted-foreground"><strong className="text-foreground">{customers.length - enabledCount}</strong> disabled</span>
      </div>

      <Button className="gap-2" disabled={busy || enabledCount === 0} onClick={() => setPopulateOpen(true)}>
        <Database className="size-4" /> {busy ? "Populating…" : "Populate Benchmark Data"}
      </Button>
      {enabledCount === 0 ? (
        <p className="text-muted-foreground text-sm">Enable benchmark for at least one customer before populating.</p>
      ) : null}

      <div className="overflow-hidden rounded-xl border bg-card">
        {filtered.length === 0 ? (
          <p className="p-6 text-center text-muted-foreground text-sm">No customers found.</p>
        ) : (
          <ul className="divide-y">
            {filtered.map((row) => (
              <li key={row.customer_id} className="flex items-center gap-3 px-4 py-3">
                <User className="size-4 shrink-0 text-muted-foreground" />
                <div className="min-w-0 flex-1">
                  <div className="flex flex-wrap items-center gap-2">
                    <span className="font-medium text-sm">{row.name}</span>
                    {row.alias_name ? (
                      <span className="rounded-md bg-muted px-2 py-0.5 text-muted-foreground text-xs">{row.alias_name}</span>
                    ) : null}
                    {row.alias_name ? (
                      <button
                        type="button"
                        className="text-muted-foreground hover:text-foreground"
                        title="Edit alias"
                        onClick={() => {
                          setEditCid(row.customer_id);
                          setEditAlias(row.alias_name ?? "");
                        }}
                      >
                        <Pencil className="size-3.5" />
                      </button>
                    ) : null}
                  </div>
                </div>
                <span
                  className={`rounded-full px-3 py-1 font-medium text-xs ${
                    row.is_enabled
                      ? "bg-emerald-100 text-emerald-700"
                      : "bg-muted text-muted-foreground"
                  }`}
                >
                  {row.is_enabled ? "ON" : "OFF"}
                </span>
              </li>
            ))}
          </ul>
        )}
      </div>

      <AlertDialog
        open={populateOpen}
        onOpenChange={(open) => {
          if (!busy) setPopulateOpen(open);
        }}
      >
        <AlertDialogContent className="sm:max-w-md">
          <AlertDialogHeader>
            <AlertDialogMedia>
              <Database className="size-5" />
            </AlertDialogMedia>
            <AlertDialogTitle>Populate benchmark data?</AlertDialogTitle>
            <AlertDialogDescription className="text-pretty">
              This recalculates shared benchmark rows for all{" "}
              <span className="font-medium text-foreground">{enabledCount}</span> enabled customer
              {enabledCount === 1 ? "" : "s"} from their portfolio history. Existing benchmark rows for
              those customers will be replaced. This may take a minute.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={busy}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              disabled={busy}
              onClick={(event) => {
                event.preventDefault();
                void confirmPopulate();
              }}
            >
              {busy ? "Populating…" : "Populate"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {editCid !== null ? (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
          <div className="w-full max-w-md rounded-xl border bg-card p-5 shadow-xl">
            <h3 className="font-semibold">Edit Alias Name</h3>
            <p className="mt-1 text-muted-foreground text-sm">Update the benchmark alias for this customer.</p>
            <Input
              className="mt-4"
              value={editAlias}
              maxLength={255}
              onChange={(event) => setEditAlias(event.target.value)}
              placeholder="Enter alias name..."
            />
            <div className="mt-5 flex justify-end gap-2">
              <Button variant="outline" disabled={busy} onClick={() => setEditCid(null)}>Cancel</Button>
              <Button disabled={busy || !editAlias.trim()} onClick={() => void saveAlias()}>Save</Button>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  );
}

function CustomerBenchmarkPanel({
  tenant,
  data,
  onRefresh,
}: {
  tenant: string;
  data: BenchmarkSettingsData;
  onRefresh: (next: BenchmarkSettingsData) => void;
}) {
  const [enabled, setEnabled] = React.useState(data.isEnabled);
  const [alias, setAlias] = React.useState(data.aliasName);
  const [compareId, setCompareId] = React.useState("");
  const [comparison, setComparison] = React.useState<BenchmarkComparisonData | null>(null);
  const [filters, setFilters] = React.useState<Filters>(EMPTY_FILTERS);
  const [fromDate, setFromDate] = React.useState(() => new Date(Date.now() - 30 * 86400000).toISOString().slice(0, 10));
  const [toDate, setToDate] = React.useState(() => new Date().toISOString().slice(0, 10));
  const [page, setPage] = React.useState(1);
  const [busy, setBusy] = React.useState(false);

  React.useEffect(() => {
    setEnabled(data.isEnabled);
    setAlias(data.aliasName);
  }, [data]);

  async function save() {
    setBusy(true);
    try {
      const result = await saveBenchmarkSettings(tenant, enabled, alias);
      onRefresh(result);
      toast.success("Benchmark Settings saved");
    } catch (saveError) {
      toast.error(saveError instanceof Error ? saveError.message : "Benchmark Settings could not be saved.");
    } finally {
      setBusy(false);
    }
  }

  async function compare() {
    if (!compareId) return;
    setBusy(true);
    try {
      const result = await compareBenchmark(tenant, {
        compareCustomerId: Number(compareId), ...filters, fromDate, toDate,
      });
      setComparison(result);
      setPage(1);
    } catch (compareError) {
      toast.error(compareError instanceof Error ? compareError.message : "Comparison could not be loaded.");
    } finally {
      setBusy(false);
    }
  }

  const options: Array<[FilterKey, string, string[]]> = comparison ? [
    ["assetClass", "Asset Class", comparison.asset_classes],
    ["assetType", "Asset Type", comparison.asset_types],
    ["banks", "Bank", comparison.banks],
    ["currency", "Currency", comparison.currencies],
    ["industry", "Industry", comparison.industries],
    ["sector", "Sector", comparison.sectors],
    ["geography", "Geography", comparison.geographies],
  ] : [];
  const rows = comparison?.comp_benchmark_rows ?? [];
  const pageCount = Math.max(1, Math.ceil(rows.length / 25));
  const pageRows = rows.slice((page - 1) * 25, page * 25);

  return (
    <div className="space-y-5">
      <div className="rounded-xl border bg-card p-5">
        <div className="flex flex-wrap items-center gap-4">
          <div className="rounded-lg bg-primary/10 p-2 text-primary"><BarChart3 className="size-5" /></div>
          <div className="mr-auto"><h2 className="font-semibold">Portfolio Benchmark</h2><p className="text-muted-foreground text-sm">Compare your portfolio performance against participating benchmarks.</p></div>
          <Switch checked={enabled} onCheckedChange={setEnabled} />
          <span className="font-medium text-sm">{enabled ? "Enabled" : "Disabled"}</span>
        </div>
        <div className="mt-5 flex flex-wrap gap-3">
          <Input className="max-w-md" value={alias} onChange={(event) => setAlias(event.target.value)} maxLength={255} placeholder="Unique benchmark alias" disabled={!enabled} />
          <Button className="gap-2" disabled={busy || (enabled && !alias.trim())} onClick={() => void save()}><Save className="size-4" />Save</Button>
        </div>
      </div>

      {enabled && (
        <div className="space-y-4 rounded-xl border bg-card p-5">
          <div><h2 className="font-semibold">Compare Benchmark</h2><p className="text-muted-foreground text-sm">Select another enabled participant and a date range.</p></div>
          <div className="flex flex-wrap gap-3">
            <Select value={compareId} onValueChange={setCompareId}><SelectTrigger className="w-72"><SelectValue placeholder="Select benchmark" /></SelectTrigger><SelectContent>{data.aliasList.map((item) => <SelectItem key={item.customer_id} value={String(item.customer_id)}>{item.benchmark_alias_name}</SelectItem>)}</SelectContent></Select>
            <Input className="w-40" type="date" value={fromDate} onChange={(event) => setFromDate(event.target.value)} />
            <Input className="w-40" type="date" value={toDate} onChange={(event) => setToDate(event.target.value)} />
            <Button className="gap-2" disabled={!compareId || busy} onClick={() => void compare()}><Search className="size-4" />Compare</Button>
          </div>
          {comparison && (
            <div className="flex flex-wrap gap-2">
              {options.map(([key, label, values]) => (
                <details key={key} className="relative">
                  <summary className="cursor-pointer list-none rounded-md border px-3 py-2 text-sm">{label}{filters[key].length ? ` (${filters[key].length})` : ""}</summary>
                  <div className="absolute z-20 mt-1 max-h-64 min-w-56 overflow-auto rounded-lg border bg-popover p-3 shadow-lg">
                    {values.map((value) => <label key={value} className="flex items-center gap-2 py-1 text-sm"><Checkbox checked={filters[key].includes(value)} onCheckedChange={(checked) => setFilters((current) => ({ ...current, [key]: checked ? [...current[key], value] : current[key].filter((item) => item !== value) }))} />{value || "Unknown"}</label>)}
                  </div>
                </details>
              ))}
              <Button variant="outline" size="sm" onClick={() => void compare()}>Apply filters</Button>
            </div>
          )}
        </div>
      )}

      {comparison && <ComparisonChart data={comparison} />}

      {comparison && rows.length > 0 && (
        <div className="overflow-hidden rounded-xl border bg-card">
          <div className="flex items-center justify-between border-b p-3"><h3 className="font-medium">Comparison details</h3><Button variant="outline" size="sm" className="gap-2" onClick={() => exportRows(rows)}><Download className="size-4" />Export CSV</Button></div>
          <div className="overflow-x-auto"><Table><TableHeader><TableRow>{Object.keys(rows[0]).map((header) => <TableHead key={header}>{header.replaceAll("_", " ")}</TableHead>)}</TableRow></TableHeader><TableBody>{pageRows.map((row, index) => <TableRow key={`${row.report_date}-${index}`}>{Object.keys(rows[0]).map((header) => <TableCell key={header}>{String(row[header] ?? "—")}</TableCell>)}</TableRow>)}</TableBody></Table></div>
          <div className="flex items-center justify-end gap-2 border-t p-3"><Button variant="outline" size="icon-sm" disabled={page <= 1} onClick={() => setPage((value) => value - 1)}><ChevronLeft /></Button><span className="text-sm">Page {page} of {pageCount}</span><Button variant="outline" size="icon-sm" disabled={page >= pageCount} onClick={() => setPage((value) => value + 1)}><ChevronRight /></Button></div>
        </div>
      )}
    </div>
  );
}

export function SettingsPanelBenchmark({ tenant }: { tenant: string }) {
  const [data, setData] = React.useState<BenchmarkSettingsData | null>(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);

  React.useEffect(() => {
    let cancelled = false;
    void loadBenchmarkSettings(tenant)
      .then((result) => {
        if (cancelled) return;
        setData(result);
      })
      .catch((loadError) => {
        if (!cancelled) setError(loadError instanceof Error ? loadError.message : "Benchmark Settings could not be loaded.");
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => { cancelled = true; };
  }, [tenant]);

  if (loading) return <p className="py-12 text-center text-muted-foreground text-sm">Loading Benchmark Settings…</p>;
  if (error || !data) return <p className="rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-destructive text-sm">{error}</p>;
  if (data.featureOff) return <p className="rounded-lg border p-5 text-muted-foreground">Benchmark is disabled for this tenant.</p>;

  const isAdminList = data.isReadOnly || (data.customerList?.length ?? 0) > 0;

  if (isAdminList) {
    return <AdminBenchmarkPanel tenant={tenant} data={data} onRefresh={setData} />;
  }

  return <CustomerBenchmarkPanel tenant={tenant} data={data} onRefresh={setData} />;
}
