"use client";

import * as React from "react";
import { resolveCustomerTenant } from "@/app/customer/_lib/resolve-customer-tenant";
import { useParams } from "next/navigation";
import { Copy, ExternalLink, Loader2 } from "lucide-react";

import { Button } from "@/components/ui/button";
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";
import { cn } from "@/lib/utils";

import { CashflowAwayCell } from "../cashflow-away-cell";
import { isStructureReportAsset } from "../../_lib/cashflow-asset-class";
import { fetchCashflowIsinDetailsClient } from "../../_lib/cashflow-isin-details-api";
import type { CashflowIsinDetails, CashflowIsinUnderlying } from "../../_lib/cashflow-isin-details-server-api";
import { resolveCashflowDetailUrl } from "../../_lib/resolve-cashflow-detail-url";
import { resolveCashflowStructureReportUrl } from "../../_lib/resolve-cashflow-structure-report-url";
import type { CashflowEvent } from "./schema";
import { CashflowStructureStatusIcon } from "./cashflow-structure-status-icon";
import {
  isCashflowFieldVisible,
  orderedCashflowDetailKeys,
} from "./cashflow-fields-catalog";
import { formatEventAmount, isNegativeAmount } from "./utils";

type CashflowEventHoverCardProps = {
  event: CashflowEvent;
  children: React.ReactNode;
  /** Keep month-grid popovers from covering the whole viewport awkwardly. */
  side?: "top" | "bottom" | "left" | "right";
  fieldVisibility?: Record<string, boolean>;
  fieldOrder?: string[];
};

function DetailRow({ label, value, mono }: { label: string; value?: string | null; mono?: boolean }) {
  if (!value) return null;
  return (
    <div className="grid grid-cols-[7.5rem_minmax(0,1fr)] gap-2 text-xs">
      <dt className="text-muted-foreground">{label}</dt>
      <dd className={cn("min-w-0 break-words font-medium text-foreground/90", mono && "font-mono tracking-tight")}>
        {value}
      </dd>
    </div>
  );
}

function UnderlyingsTable({ rows, hasAway }: { rows: CashflowIsinUnderlying[]; hasAway: boolean }) {
  if (rows.length === 0) {
    return <p className="py-2 text-center text-muted-foreground text-xs">No underlying records.</p>;
  }

  return (
    <ul className="space-y-2">
      {rows.map((row) => (
        <li key={row.isin} className="rounded-lg border border-border/60 bg-muted/20 px-3 py-2.5 text-[11px]">
          <div className="flex items-start justify-between gap-2">
            <div className="min-w-0">
              <p className="truncate font-medium text-foreground/90" title={row.name}>
                {row.name || "—"}
              </p>
              <p className="mt-0.5 font-mono text-[10px] text-muted-foreground tracking-tight">{row.isin}</p>
            </div>
            {row.currency ? (
              <span className="shrink-0 rounded-full bg-muted px-2 py-0.5 font-medium text-muted-foreground text-[10px]">
                {row.currency}
              </span>
            ) : null}
          </div>
          {hasAway ? (
            <div className="mt-2 grid grid-cols-2 gap-2 border-t border-border/50 pt-2">
              <div>
                <p className="text-[10px] text-muted-foreground">% Away from Initial</p>
                <CashflowAwayCell value={row.awayFromInitial} negative={row.awayFromInitialNegative} />
              </div>
              <div>
                <p className="text-[10px] text-muted-foreground">% Away from Strike</p>
                <CashflowAwayCell value={row.awayFromStrike} negative={row.awayFromStrikeNegative} />
              </div>
            </div>
          ) : null}
        </li>
      ))}
    </ul>
  );
}

function detailValueForKey(event: CashflowEvent, key: string): { label: string; value?: string | null; mono?: boolean } | null {
  const isStructure = isStructureReportAsset(event.assetClassCode);
  switch (key) {
    case "assetClass":
      return { label: "Asset Class", value: event.assetClassLabel };
    case "date":
      return { label: "Date", value: event.eventDateLabel || event.date };
    case "user":
      return { label: "User", value: event.userLabel || event.userName || event.uidTitle };
    case "ref":
      if (!event.uidTitle || event.uidTitle === event.userLabel) return null;
      return { label: "Ref", value: event.uidTitle, mono: true };
    case "isin":
      return { label: "ISIN", value: event.isin, mono: true };
    case "ticker":
      if (!event.ticker || event.ticker === event.isin) return null;
      return { label: "Ticker", value: event.ticker, mono: true };
    case "name":
      return { label: "Name", value: event.name };
    case "quantity":
      return { label: "Quantity", value: event.quantity };
    case "eventKind":
      return { label: "Type", value: event.eventKind };
    case "coupon":
      return { label: "Coupon", value: event.coupon };
    case "periodicAmount":
      return { label: "Periodic Amount", value: event.periodicAmount };
    case "perShare":
      return { label: "Per Share", value: event.perShare };
    case "earlyRedemption":
      if (!isStructure) return null;
      return { label: "Early Redm", value: String(event.earlyRedemption) };
    case "delivery":
      if (!isStructure) return null;
      return { label: "Delivery", value: String(event.delivery) };
    default:
      return null;
  }
}

export function CashflowEventHoverCard({
  event,
  children,
  side = "right",
  fieldVisibility,
  fieldOrder,
}: CashflowEventHoverCardProps) {
  const params = useParams<{ tenant?: string }>();
  const tenant = typeof params?.tenant === "string" && params.tenant.trim() ? params.tenant.trim() : resolveCustomerTenant();

  const [open, setOpen] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const [details, setDetails] = React.useState<CashflowIsinDetails | null>(null);
  const [copied, setCopied] = React.useState(false);

  const show = (key: string) => isCashflowFieldVisible(fieldVisibility, key);
  const amountText = event.amountDisplay || formatEventAmount(event.amount, event.currency);
  const negative = isNegativeAmount(event.amount);
  const isStructure = isStructureReportAsset(event.assetClassCode) && Boolean(event.isin);
  const detailHref = React.useMemo(
    () =>
      resolveCashflowDetailUrl({
        detailUrl: event.detailUrl,
        tenant,
        assetClassCode: event.assetClassCode,
        customerId: event.customerId,
      }),
    [event.assetClassCode, event.customerId, event.detailUrl, tenant],
  );
  const structureReportHref = React.useMemo(
    () =>
      resolveCashflowStructureReportUrl({
        structureReportUrl: event.structureReportUrl,
        tenant,
        assetClassCode: event.assetClassCode,
        isin: event.isin,
        clientId: event.customerId,
      }),
    [event.assetClassCode, event.customerId, event.isin, event.structureReportUrl, tenant],
  );
  const accumulatorReportHref = event.accumulatorReportUrl;

  const detailRows = React.useMemo(() => {
    const keys = orderedCashflowDetailKeys(fieldOrder);
    const rows: { key: string; label: string; value: string; mono?: boolean }[] = [];
    for (const key of keys) {
      if (!isCashflowFieldVisible(fieldVisibility, key)) continue;
      const row = detailValueForKey(event, key);
      if (!row?.value) continue;
      rows.push({ key, label: row.label, value: row.value, mono: row.mono });
    }
    return rows;
  }, [event, fieldOrder, fieldVisibility]);

  React.useEffect(() => {
    if (!open || !isStructure || !event.isin || details) return;

    let cancelled = false;
    setLoading(true);
    setError(null);

    const timer = window.setTimeout(() => {
      void fetchCashflowIsinDetailsClient(tenant, event.isin, {
        customerId: event.customerId,
        // Prefer Ref ID so shared product ISINs resolve the same Sr as Structure Report.
        uid: event.refId || null,
        structureId: event.structureId || null,
      }).then((result) => {
        if (cancelled) return;
        setLoading(false);
        if (result.errorMessage || !result.data) {
          setError(result.errorMessage ?? "Could not load underlyings.");
          return;
        }
        setDetails(result.data);
      });
    }, 80);

    return () => {
      cancelled = true;
      window.clearTimeout(timer);
    };
  }, [open, isStructure, event.isin, event.customerId, event.refId, event.structureId, tenant, details]);

  const copyIsin = async () => {
    if (!event.isin) return;
    try {
      await navigator.clipboard.writeText(event.isin);
      setCopied(true);
      window.setTimeout(() => setCopied(false), 1200);
    } catch {
      // ignore
    }
  };

  // Header identity is always shown (status, type, asset class, heading) — not field-prefs gated.
  const headingText =
    event.heading || (event.refId ? `Ref ID ${event.refId}` : event.shortLabel);

  return (
    <HoverCard open={open} onOpenChange={setOpen} openDelay={80} closeDelay={120}>
      <HoverCardTrigger asChild>{children}</HoverCardTrigger>
      <HoverCardContent
        side={side}
        align="start"
        sideOffset={8}
        avoidCollisions
        collisionPadding={12}
        sticky="always"
        className="z-[80] w-[min(92vw,26rem)] max-h-[min(calc(100vh-1.5rem),var(--radix-hover-card-content-available-height))] overflow-y-auto border-border/60 bg-popover p-0 shadow-xl ring-1 ring-black/5 dark:ring-white/10"
      >
        <div
          className="border-b border-border/60 bg-muted/30 px-4 py-3"
          style={{ borderTop: `3px solid ${event.color}` }}
        >
          <div className="flex flex-wrap items-center gap-2">
            {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-[10px] uppercase tracking-[0.12em]"
              style={{ backgroundColor: `${event.color}24`, color: event.textColor }}
            >
              {event.shortLabel}
            </span>
            {event.assetClassLabel ? (
              <span className="text-muted-foreground text-xs">{event.assetClassLabel}</span>
            ) : null}
          </div>
          <p className="mt-1.5 font-semibold text-sm tracking-tight">{headingText}</p>
        </div>

        <div className="space-y-2.5 px-4 py-3">
          {detailRows.length > 0 ? (
            <dl className="space-y-1.5">
              {detailRows.map((row) => (
                <DetailRow key={row.key} label={row.label} value={row.value} mono={row.mono} />
              ))}
            </dl>
          ) : null}

          {show("amount") && amountText ? (
            <p
              className={cn(
                "font-semibold text-lg tabular-nums tracking-tight",
                negative ? "text-rose-600 dark:text-rose-400" : "text-foreground",
              )}
            >
              {amountText}
            </p>
          ) : show("currency") && event.currency ? (
            <p className="font-medium text-sm tabular-nums text-foreground/80">{event.currency}</p>
          ) : null}

          {(show("isin") && event.isin) || detailHref || structureReportHref || accumulatorReportHref ? (
            <div className="flex flex-wrap gap-2">
              {show("isin") && event.isin ? (
                <Button type="button" variant="outline" size="sm" className="h-8 gap-1.5 rounded-full text-xs" onClick={copyIsin}>
                  <Copy className="size-3.5" />
                  {copied ? "Copied" : "Copy ISIN"}
                </Button>
              ) : null}
              {detailHref ? (
                <Button type="button" variant="outline" size="sm" className="h-8 gap-1.5 rounded-full text-xs" asChild>
                  <a href={detailHref} target="_blank" rel="noreferrer">
                    <ExternalLink className="size-3.5" />
                    More details
                  </a>
                </Button>
              ) : null}
              {structureReportHref ? (
                <Button
                  type="button"
                  size="sm"
                  className="h-8 gap-1.5 rounded-full bg-rose-800 text-xs text-white hover:bg-rose-700"
                  asChild
                >
                  <a href={structureReportHref} target="_blank" rel="noreferrer">
                    Structure report
                  </a>
                </Button>
              ) : null}
              {accumulatorReportHref ? (
                <Button
                  type="button"
                  size="sm"
                  className="h-8 gap-1.5 rounded-full bg-sky-800 text-xs text-white hover:bg-sky-700"
                  asChild
                >
                  <a href={accumulatorReportHref} target="_blank" rel="noreferrer">
                    Accumulator report
                  </a>
                </Button>
              ) : null}
            </div>
          ) : null}
        </div>

        {isStructure ? (
          <div className="border-t border-border/60 px-4 py-3">
            <p className="mb-2 font-medium text-[11px] text-muted-foreground uppercase tracking-[0.12em]">
              Underlying details
            </p>
            {loading ? (
              <div className="flex items-center gap-2 py-3 text-muted-foreground text-xs">
                <Loader2 className="size-3.5 animate-spin" />
                Loading underlyings…
              </div>
            ) : error ? (
              <p className="py-2 text-destructive text-xs">{error}</p>
            ) : details ? (
              <UnderlyingsTable rows={details.underlyings} hasAway={details.hasAway} />
            ) : null}
          </div>
        ) : null}
      </HoverCardContent>
    </HoverCard>
  );
}
