"use client";

import Link from "next/link";
import { Fragment, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { ArrowLeft, CalendarDays, ListOrdered, ScrollText } from "lucide-react";
import { toast } from "sonner";

import type {
  AccumulatorScheduleColumn,
  AccumulatorScheduleMode,
  AccumulatorSchedulePeriod,
  AccumulatorScheduleRow,
  StockAccumulatorScheduleView as ScheduleViewModel,
} from "@/app/customer/[tenant]/stock-accumulator/_lib/stock-accumulator-server-api";
import { deleteStockAccumulatorClient } from "@/app/customer/[tenant]/stock/_lib/stock-api";
import { RecordViewDeleteButton } from "@/app/customer/_components/record-view/record-view-delete-button";
import { ErrorBanner } from "@/components/shared/error-banner";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { cn } from "@/lib/utils";

type Props = {
  tenant: string;
  id: string;
  view: ScheduleViewModel;
  backHref: string;
};

export function StockAccumulatorScheduleView({ tenant, id, view, backHref }: Props) {
  const router = useRouter();
  const localId = id.split("-")[0] ?? id;

  function switchMode(mode: AccumulatorScheduleMode) {
    const params = new URLSearchParams();
    if (mode === "advance") params.set("mode", "advance");
    const qs = params.toString();
    router.push(`/customer/${tenant}/stock-accumulator/${encodeURIComponent(id)}${qs ? `?${qs}` : ""}`);
  }

  async function handleDelete() {
    try {
      await deleteStockAccumulatorClient(localId);
      toast.success("Stock accumulator deleted", {
        description: `${view.refId || localId} has been removed.`,
      });
      router.push(backHref);
      router.refresh();
    } catch (error) {
      toast.error(
        error instanceof Error ? error.message : "Stock accumulator could not be deleted.",
      );
      throw error;
    }
  }

  const isAdvance = view.mode === "advance" || view.layout === "accordion";

  return (
    <div className="flex flex-col gap-4">
      <div className="flex flex-col gap-3 border-b pb-3 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-start gap-2">
          <ScrollText className="mt-0.5 size-5 text-violet-600" />
          <div>
            <h1 className="font-semibold text-base tracking-tight">{view.heading}</h1>
            {view.refId ? (
              <p className="text-muted-foreground text-sm">Ref. ID {view.refId}</p>
            ) : null}
          </div>
        </div>
        <div className="flex flex-wrap items-center gap-2">
          <Button
            type="button"
            size="sm"
            variant={view.mode === "table" ? "default" : "outline"}
            onClick={() => switchMode("table")}
          >
            <ListOrdered className="size-4" />
            Table view
          </Button>
          <Button
            type="button"
            size="sm"
            variant={isAdvance ? "default" : "outline"}
            onClick={() => switchMode("advance")}
          >
            <CalendarDays className="size-4" />
            Advance view
          </Button>
          <Button type="button" size="sm" variant="ghost" asChild>
            <Link href={backHref}>
              <ArrowLeft className="size-4" />
              Back to transactions
            </Link>
          </Button>
          {!view.errorMessage ? (
            <RecordViewDeleteButton
              onDelete={handleDelete}
              entityLabel="stock accumulator"
              description={
                <>
                  <span className="font-medium text-foreground">{view.refId || localId}</span> will
                  be removed. This cannot be undone.
                </>
              }
            />
          ) : null}
        </div>
      </div>

      <ErrorBanner message={view.errorMessage} />

      {view.header.length > 0 ? (
        <div className="grid gap-x-6 gap-y-2 rounded-lg border bg-card p-4 sm:grid-cols-2">
          {view.header.map((field) => (
            <div key={`${field.label}-${field.value}`} className="grid grid-cols-[minmax(0,1fr)_minmax(0,1.2fr)] gap-3 text-sm">
              <dt className="text-muted-foreground font-medium">{field.label}</dt>
              <dd className="font-medium break-words">{field.value}</dd>
            </div>
          ))}
        </div>
      ) : null}

      {isAdvance ? <AdvanceAccordionView view={view} /> : <FlatScheduleTable view={view} />}
    </div>
  );
}

function FlatScheduleTable({ view }: { view: ScheduleViewModel }) {
  return (
    <div className="overflow-x-auto rounded-lg border bg-card">
      <ScheduleTable columns={view.columns} rows={view.rows} />
    </div>
  );
}

function AdvanceAccordionView({ view }: { view: ScheduleViewModel }) {
  const periodKeys = useMemo(
    () => view.periods.map((period) => `period-${period.period}`),
    [view.periods],
  );
  const [openItems, setOpenItems] = useState<string[]>(() =>
    periodKeys.length > 0 ? [periodKeys[0]] : [],
  );

  function expandAll() {
    setOpenItems(periodKeys);
  }

  function collapseAll() {
    setOpenItems([]);
  }

  if (view.periods.length === 0) {
    return (
      <div className="overflow-x-auto rounded-lg border bg-card">
        <ScheduleTable columns={view.columns} rows={view.rows} />
      </div>
    );
  }

  return (
    <div className="flex flex-col gap-3">
      {view.legend ? (
        <p className="rounded-lg border bg-muted/30 px-3 py-2 text-muted-foreground text-sm leading-relaxed">
          {view.legend}
        </p>
      ) : null}

      <div className="flex flex-wrap items-center gap-2">
        <Button type="button" size="sm" variant="outline" onClick={expandAll}>
          Expand all
        </Button>
        <Button type="button" size="sm" variant="outline" onClick={collapseAll}>
          Collapse all
        </Button>
        {view.totals ? (
          <div className="ml-auto flex flex-wrap gap-x-4 gap-y-1 text-muted-foreground text-xs sm:text-sm">
            {view.totals.quantityDisplay ? <span>Qty {view.totals.quantityDisplay}</span> : null}
            {view.totals.expectedQtyDisplay ? (
              <span>Delivered qty {view.totals.expectedQtyDisplay}</span>
            ) : null}
            {view.totals.expectedAmtDisplay ? (
              <span>Delivered amt {view.totals.expectedAmtDisplay}</span>
            ) : null}
          </div>
        ) : null}
      </div>

      <Accordion
        type="multiple"
        value={openItems}
        onValueChange={setOpenItems}
        className="rounded-lg border bg-card"
      >
        {view.periods.map((period) => (
          <PeriodAccordionItem key={period.period} period={period} columns={view.columns} />
        ))}
      </Accordion>
    </div>
  );
}

function PeriodAccordionItem({
  period,
  columns,
}: {
  period: AccumulatorSchedulePeriod;
  columns: AccumulatorScheduleColumn[];
}) {
  const value = `period-${period.period}`;
  const range =
    period.dateFrom && period.dateTo
      ? period.dateFrom === period.dateTo
        ? period.dateFrom
        : `${period.dateFrom} → ${period.dateTo}`
      : "—";

  return (
    <AccordionItem value={value} className="border-b px-3 last:border-b-0">
      <AccordionTrigger className="items-center gap-3 py-3 hover:no-underline">
        <div className="flex min-w-0 flex-1 flex-col gap-1.5 text-left">
          <div className="flex flex-wrap items-center gap-2">
            <span className="font-semibold text-sm">{period.title}</span>
            <Badge variant={period.settled ? "secondary" : "outline"}>
              {period.settled ? "Settled" : "Settles"} {period.settlement || "—"}
            </Badge>
            <span className="text-muted-foreground text-xs">{range}</span>
          </div>
          <div className="flex flex-wrap gap-x-3 gap-y-1 text-muted-foreground text-xs">
            <span>{period.datesCount} dates</span>
            {period.skippedCount > 0 ? <span>{period.skippedCount} skipped</span> : null}
            <span>Expected {period.expectedQtyDisplay || "—"}</span>
            <span>Pending {period.pendingDisplay || "—"}</span>
            <span>
              ≥ strike {period.n1} · &lt; strike {period.n2}
              {period.pendingDates > 0 ? ` · pending ${period.pendingDates}` : ""}
            </span>
          </div>
        </div>
      </AccordionTrigger>
      <AccordionContent className="pb-3">
        {period.formula.s || period.formula.total ? (
          <p className="mb-2 rounded-md bg-muted/40 px-3 py-2 text-muted-foreground text-xs leading-relaxed">
            <span className="mr-1 font-medium text-foreground">Shares to Deliver</span>
            = (S × N1) + [L × (S × N2)] = ({period.formula.s || "S"} × {period.formula.n1}) + [
            {period.formula.l || "L"} × ({period.formula.s || "S"} × {period.formula.n2})]
            {period.formula.total ? (
              <>
                {" "}
                = <strong className="text-foreground">{period.formula.total}</strong>
              </>
            ) : null}
            <span className="mt-1 block">
              S = shares/period, N1 = close ≥ strike, N2 = close &lt; strike, L = leverage
              {period.pendingDates > 0
                ? ` · ${period.pendingDates} no-data date(s) excluded`
                : ""}
            </span>
          </p>
        ) : null}
        <div className="overflow-x-auto rounded-md border">
          <ScheduleTable columns={columns} rows={period.rows} showDeliveryBadges />
        </div>
      </AccordionContent>
    </AccordionItem>
  );
}

function ScheduleTable({
  columns,
  rows,
  showDeliveryBadges = false,
}: {
  columns: AccumulatorScheduleColumn[];
  rows: AccumulatorScheduleRow[];
  showDeliveryBadges?: boolean;
}) {
  return (
    <Table>
      <TableHeader>
        <TableRow className="bg-muted/20 hover:bg-muted/20">
          {columns.map((column) => (
            <TableHead key={column.key} className="h-10 whitespace-nowrap px-2 text-xs">
              {column.label}
            </TableHead>
          ))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.length === 0 ? (
          <TableRow>
            <TableCell
              colSpan={Math.max(columns.length, 1)}
              className="h-24 text-center text-muted-foreground text-sm"
            >
              No schedule rows.
            </TableCell>
          </TableRow>
        ) : (
          rows.map((row, index) => {
            const skipped = Array.isArray(row.skipped) ? row.skipped : [];
            const skipLabel =
              skipped.length === 1 ? "Skipped:" : `Skipped ${skipped.length} days:`;
            const skipParts = skipped
              .map((item) => {
                const date = stringCell(item.date);
                if (!date) return "";
                const dow = weekdayShort(date);
                const reason = stringCell(item.reason) || "Non-business day";
                return dow ? `${date} (${dow}) — ${reason}` : `${date} — ${reason}`;
              })
              .filter(Boolean);

            return (
              <Fragment key={`${row.start_date ?? "row"}-${row.serial_no_display ?? index}`}>
                {skipParts.length > 0 ? (
                  <TableRow className="bg-amber-50/70 hover:bg-amber-50/70 dark:bg-amber-950/20">
                    <TableCell className="px-2 py-1.5" />
                    <TableCell
                      colSpan={Math.max(columns.length - 1, 1)}
                      className="px-2 py-1.5 text-muted-foreground text-xs leading-relaxed"
                    >
                      <span className="mr-1.5 font-medium text-amber-800 dark:text-amber-200">
                        {skipLabel}
                      </span>
                      {skipParts.join("  ·  ")}
                    </TableCell>
                  </TableRow>
                ) : null}
                <TableRow className={cn(index % 2 === 0 && "bg-muted/5")}>
                  {columns.map((column) => (
                    <TableCell key={column.key} className="whitespace-nowrap px-2 py-2 text-sm">
                      {renderCell(row, column.key, showDeliveryBadges)}
                    </TableCell>
                  ))}
                </TableRow>
              </Fragment>
            );
          })
        )}
      </TableBody>
    </Table>
  );
}

function renderCell(row: AccumulatorScheduleRow, key: string, showDeliveryBadges: boolean) {
  if (key === "start_date") {
    const date = stringCell(row.start_date);
    const dow = stringCell(row.dow);
    return dow ? `${date} (${dow})` : date;
  }

  if (showDeliveryBadges && (key === "close_display" || key === "delivered_qty_display")) {
    const value = stringCell(row[key]);
    const badge = stringCell(row.delivered_badge);
    const status = stringCell(row.delivered_status);
    return (
      <span className="inline-flex items-center gap-1.5">
        <span
          className={cn(
            status === "nodata" && "text-destructive",
            status === "future" && "text-muted-foreground",
          )}
        >
          {value}
        </span>
        {badge && key === "close_display" ? (
          <Badge
            variant="outline"
            className={cn(
              "px-1.5 py-0 text-[10px]",
              status === "levered" && "border-amber-500/40 text-amber-700",
              status === "base" && "border-emerald-500/40 text-emerald-700",
            )}
          >
            {badge}
          </Badge>
        ) : null}
      </span>
    );
  }

  return stringCell(row[key]);
}

function stringCell(value: unknown): string {
  if (value == null) return "";
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
    return String(value);
  }
  return "";
}

function weekdayShort(date: string): string {
  const ts = Date.parse(`${date}T00:00:00`);
  if (Number.isNaN(ts)) return "";
  return new Intl.DateTimeFormat("en-US", { weekday: "short" }).format(new Date(ts));
}
