"use client";

import * as React from "react";
import { format, parseISO } from "date-fns";
import { CalendarDays, Info, Search, X } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Sheet, SheetContent, SheetDescription, SheetTitle } from "@/components/ui/sheet";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";

import { isStructureReportAsset } from "../../_lib/cashflow-asset-class";
import type { CashflowEvent } from "./schema";
import { CashflowEventHoverCard } from "./cashflow-event-hover-card";
import { isCashflowFieldVisible } from "./cashflow-fields-catalog";
import { CashflowStructureStatusIcon } from "./cashflow-structure-status-icon";
import { formatEventAmount, isNegativeAmount } from "./utils";

type CashflowDaySheetProps = {
  date: string | null;
  events: CashflowEvent[];
  open: boolean;
  onOpenChange: (open: boolean) => void;
  detailVisibility?: Record<string, boolean>;
  detailOrder?: string[];
};

const HIDDEN_DETAIL_LABELS = new Set([
  "amount",
  "name",
  "isin",
  "ticker",
  "quantity",
  "type",
  "asset class",
  "date",
  "heading",
  "user",
  "ref id",
  "periodic amount",
  "per share",
]);

function filterDayEvents(events: CashflowEvent[], query: string) {
  const q = query.trim().toLowerCase();
  if (!q) return events;

  return events.filter((event) => {
    const haystack = [
      event.title,
      event.heading,
      event.assetClassLabel,
      event.shortLabel,
      event.isin,
      event.name,
      event.refId,
      event.currency,
      event.amountDisplay,
      event.eventKind,
      event.userLabel,
      event.uidTitle,
      ...event.detailLines.map((line) => `${line.label} ${line.value}`),
    ]
      .join(" ")
      .toLowerCase();
    return haystack.includes(q);
  });
}

function EventMetaPill({ children, mono }: { children: React.ReactNode; mono?: boolean }) {
  return (
    <span
      className={cn(
        "inline-flex max-w-full items-center truncate rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground",
        mono && "font-mono tracking-tight",
      )}
    >
      {children}
    </span>
  );
}

function CashflowEventCard({
  event,
  detailVisibility,
  detailOrder,
}: {
  event: CashflowEvent;
  detailVisibility?: Record<string, boolean>;
  detailOrder?: string[];
}) {
  const show = (key: string) => isCashflowFieldVisible(detailVisibility, key);
  const amountText = event.amountDisplay || formatEventAmount(event.amount, event.currency);
  const negative = isNegativeAmount(event.amount);
  const extraLines = event.detailLines.filter(
    (line) => !HIDDEN_DETAIL_LABELS.has(line.label.toLowerCase()),
  );
  // Card header identity always stays visible (status, type, asset class, heading).
  const headingSuffix =
    event.heading || (event.refId ? `Ref ID ${event.refId}` : null);

  return (
    <li>
      <CashflowEventHoverCard
        event={event}
        side="left"
        fieldVisibility={detailVisibility}
        fieldOrder={detailOrder}
      >
        <div className="group relative overflow-hidden rounded-xl border border-border/60 bg-card px-3 py-2.5 shadow-sm transition-colors hover:shadow-md">
          <span
            aria-hidden
            className="absolute inset-y-0 left-0 w-[3px]"
            style={{ backgroundColor: event.color }}
          />

          <div className="flex items-start justify-between gap-2 pl-2.5">
            <div className="min-w-0 flex-1">
              <div className="flex flex-wrap items-center gap-1.5">
                {isStructureReportAsset(event.assetClassCode) ? (
                  <CashflowStructureStatusIcon
                    earlyRedemption={event.earlyRedemption}
                    delivery={event.delivery}
                    size="md"
                  />
                ) : null}
                <span
                  className="inline-flex items-center rounded-full px-2 py-0.5 font-semibold text-[9px] uppercase tracking-[0.1em]"
                  style={{
                    backgroundColor: `${event.color}24`,
                    color: event.textColor,
                  }}
                >
                  {event.shortLabel}
                </span>
                {event.assetClassLabel && event.assetClassLabel !== event.shortLabel ? (
                  <span className="truncate text-muted-foreground text-[11px]">{event.assetClassLabel}</span>
                ) : null}
                {headingSuffix ? (
                  <span className="truncate text-muted-foreground text-[11px]">· {headingSuffix}</span>
                ) : null}
              </div>
            </div>
            {show("currency") && event.currency ? (
              <span className="shrink-0 rounded-full bg-muted px-2 py-0.5 font-mono text-[10px] text-muted-foreground">
                {event.currency}
              </span>
            ) : null}
          </div>

          {show("amount") && amountText ? (
            <p
              className={cn(
                "mt-1.5 pl-2.5 font-semibold text-base tabular-nums tracking-tight",
                negative ? "text-rose-600 dark:text-rose-400" : "text-foreground",
              )}
            >
              {amountText}
            </p>
          ) : null}

          {show("name") && event.name ? (
            <p className="mt-0.5 truncate pl-2.5 text-xs text-foreground/80 leading-snug">{event.name}</p>
          ) : null}

          <div className="mt-2 flex flex-wrap gap-1 pl-2.5">
            {show("isin") && event.isin ? <EventMetaPill mono>{event.isin}</EventMetaPill> : null}
            {show("ticker") && event.ticker && event.ticker !== event.isin ? (
              <EventMetaPill mono>{event.ticker}</EventMetaPill>
            ) : null}
            {show("user") && (event.userLabel || event.uidTitle) ? (
              <EventMetaPill>{event.userLabel || event.uidTitle}</EventMetaPill>
            ) : null}
            {show("quantity") && event.quantity ? <EventMetaPill>Qty {event.quantity}</EventMetaPill> : null}
            {show("eventKind") && event.eventKind ? <EventMetaPill>{event.eventKind}</EventMetaPill> : null}
            {show("periodicAmount") && event.periodicAmount ? (
              <EventMetaPill>Periodic {event.periodicAmount}</EventMetaPill>
            ) : null}
            {show("perShare") && event.perShare ? (
              <EventMetaPill>Per share {event.perShare}</EventMetaPill>
            ) : null}
          </div>

          {extraLines.length > 0 ? (
            <dl className="mt-2 space-y-1 border-t border-border/45 pt-2 pl-2.5">
              {extraLines.map((line, index) => (
                <div key={`${line.label}-${index}`} className="flex items-baseline justify-between gap-3">
                  <dt className="shrink-0 text-[10px] text-muted-foreground uppercase tracking-wide">
                    {line.label}
                  </dt>
                  <dd className="min-w-0 truncate text-right font-medium text-xs">{line.value}</dd>
                </div>
              ))}
            </dl>
          ) : null}
        </div>
      </CashflowEventHoverCard>
    </li>
  );
}

export function CashflowDaySheet({
  date,
  events,
  open,
  onOpenChange,
  detailVisibility,
  detailOrder,
}: CashflowDaySheetProps) {
  const [find, setFind] = React.useState("");
  const [openedFor, setOpenedFor] = React.useState<string | null>(null);

  if (open && openedFor !== date) {
    setOpenedFor(date);
    setFind("");
  }

  const parsed = date ? parseISO(date) : null;
  const title = parsed ? format(parsed, "EEEE, d MMMM yyyy") : "Day details";
  const filteredEvents = React.useMemo(() => filterDayEvents(events, find), [events, find]);

  const totalByCurrency = React.useMemo(() => {
    const acc: Record<string, number> = {};
    for (const event of events) {
      if (!event.currency || !event.amount) continue;
      acc[event.currency] = (acc[event.currency] ?? 0) + event.amount;
    }
    return Object.entries(acc).sort(([a], [b]) => a.localeCompare(b));
  }, [events]);

  const badgeLabel = find.trim()
    ? `${filteredEvents.length}/${events.length}`
    : `${events.length} event${events.length === 1 ? "" : "s"}`;

  const description = find.trim()
    ? `${filteredEvents.length} of ${events.length} events match your search.`
    : `${events.length} cashflow event${events.length === 1 ? "" : "s"} for this day. Hover a card for full details.`;

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent
        side="right"
        showCloseButton={false}
        className={cn(
          "flex h-dvh w-full flex-col gap-0 overflow-hidden bg-muted/30 p-0",
          "data-[side=right]:sm:max-w-2xl",
        )}
      >
        <div className="shrink-0 space-y-1.5 px-4 pt-3 pb-1">
          <p className="text-muted-foreground text-[10px] font-semibold tracking-widest uppercase">
            Cashflow
          </p>
          <div className="flex items-center justify-between gap-2">
            <SheetTitle className="flex min-w-0 items-center gap-2 text-left text-base font-semibold tracking-tight">
              <span className="flex size-8 shrink-0 items-center justify-center rounded-xl bg-primary text-primary-foreground shadow-md shadow-primary/25">
                <CalendarDays className="size-3.5" />
              </span>
              <span className="truncate">{title}</span>
              <TooltipProvider delayDuration={200}>
                <Tooltip>
                  <TooltipTrigger asChild>
                    <button
                      type="button"
                      className="inline-flex size-6 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                      aria-label="About day details"
                    >
                      <Info className="size-3.5" />
                    </button>
                  </TooltipTrigger>
                  <TooltipContent side="bottom" className="max-w-[240px] text-xs leading-relaxed">
                    {description}
                  </TooltipContent>
                </Tooltip>
              </TooltipProvider>
              <span className="inline-flex shrink-0 items-center rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium tabular-nums text-muted-foreground">
                {badgeLabel}
              </span>
            </SheetTitle>
            <Button
              type="button"
              variant="ghost"
              size="icon-sm"
              className="rounded-lg"
              onClick={() => onOpenChange(false)}
              aria-label="Close day details"
            >
              <X className="size-4" />
            </Button>
          </div>
          <SheetDescription className="sr-only">{description}</SheetDescription>
        </div>

        <div className="flex min-h-0 flex-1 flex-col gap-2.5 overflow-y-auto px-4 py-2.5">
          <section className="flex flex-col gap-2.5 rounded-2xl border border-border/60 bg-card p-2.5 shadow-sm">
            {totalByCurrency.length > 0 ? (
              <div>
                <p className="mb-1.5 font-semibold text-[10px] text-muted-foreground uppercase tracking-wider">
                  Totals by currency
                </p>
                <ul className="flex flex-wrap gap-1.5" aria-label="Totals by currency">
                  {totalByCurrency.map(([currency, total]) => {
                    const negative = isNegativeAmount(total);
                    return (
                      <li
                        key={currency}
                        className="flex min-w-[6.5rem] flex-1 flex-col rounded-lg border border-border/50 bg-muted/30 px-2.5 py-1.5 sm:min-w-[7.5rem] sm:flex-none"
                      >
                        <span className="font-medium text-[9px] text-muted-foreground uppercase tracking-[0.12em]">
                          {currency}
                        </span>
                        <span
                          className={cn(
                            "mt-0.5 font-semibold text-xs tabular-nums tracking-tight",
                            negative ? "text-rose-600 dark:text-rose-400" : "text-foreground",
                          )}
                        >
                          {total.toLocaleString("en-US", {
                            minimumFractionDigits: 2,
                            maximumFractionDigits: 2,
                          })}
                        </span>
                      </li>
                    );
                  })}
                </ul>
              </div>
            ) : null}

            <div className="relative">
              <Search className="pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-foreground" />
              <Input
                value={find}
                onChange={(e) => setFind(e.target.value)}
                placeholder="Find title, ISIN, asset class…"
                className="h-8 rounded-lg border-border/60 bg-white pl-8 pr-8 text-sm shadow-none dark:bg-background"
                aria-label="Search day events"
              />
              {find ? (
                <button
                  type="button"
                  onClick={() => setFind("")}
                  className="absolute top-1/2 right-2 -translate-y-1/2 rounded-md p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
                  aria-label="Clear search"
                >
                  <X className="size-3.5" />
                </button>
              ) : null}
            </div>
          </section>

          <ul className="space-y-2 pb-3">
            {events.length === 0 ? (
              <li className="rounded-xl border border-dashed border-border/70 bg-card/60 py-8 text-center text-muted-foreground text-sm">
                No events on this day.
              </li>
            ) : filteredEvents.length === 0 ? (
              <li className="rounded-xl border border-dashed border-border/70 bg-card/60 py-8 text-center text-muted-foreground text-sm">
                No events match your search.
              </li>
            ) : (
              filteredEvents.map((event) => (
                <CashflowEventCard
                  key={event.id}
                  event={event}
                  detailVisibility={detailVisibility}
                  detailOrder={detailOrder}
                />
              ))
            )}
          </ul>
        </div>
      </SheetContent>
    </Sheet>
  );
}
