"use client";

import * as React from "react";
import { ArrowRightLeft, Check, ChevronDown, Info, XCircle } from "lucide-react";

import { Button } from "@/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverDescription,
  PopoverHeader,
  PopoverTitle,
  PopoverTrigger,
} from "@/components/ui/popover";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { formatAmount } from "@/lib/format/numbers";
import { mapStructureProductType } from "@/lib/structure-product-type";
import { cn } from "@/lib/utils";

import type {
  StructuredProductDateItem,
  StructuredProductDateSeries,
  StructuredProductLegacyField,
  StructuredProductReportRow,
} from "../../_lib/structured-product-types";

/** True when the row’s product is PHX - E (Autocall Memory). */
export function isPhoenixEProductRow(row: StructuredProductReportRow): boolean {
  const raw = `${row.product?.name ?? ""} ${String(row.values?.product_typeAbsolute ?? "")}`;
  return /PHX\s*[-–—]\s*E/i.test(raw);
}

/** PHX-E Autocall Memory: underlying label + sticky P with click Accept/Reject. */
export function PhoenixEMemoryUnderlying({
  row,
  pending,
  onAccept,
  onReject,
}: {
  row: StructuredProductReportRow;
  pending: boolean;
  onAccept: () => void;
  onReject: () => void;
}) {
  const name = String(reportCellValue(row, "Underlying1") ?? "").trim() || "—";
  const memoryP = Boolean(row.underlyingMeta?.memoryP);
  const memoryPDate = String(row.underlyingMeta?.memoryPDate ?? "").trim() || null;
  const canAct = Boolean(row.underlyingMeta?.legActionId);

  const pTitle = memoryP
    ? memoryPDate
      ? `Autocall memory P since ${memoryPDate}`
      : "Autocall memory P"
    : "Autocall memory — Accept to stamp P (or wait for a future +ive obs)";

  return (
    <Popover>
      <PopoverTrigger asChild>
        <button
          type="button"
          className={cn(
            "group inline-flex max-w-full cursor-pointer items-center gap-1.5 rounded-sm px-0.5 py-0.5 text-left",
            "outline-none focus-visible:ring-2 focus-visible:ring-ring/50",
          )}
          onClick={(event) => event.stopPropagation()}
          aria-label={`${name} — ${pTitle}. Open Accept or Reject.`}
        >
          {/* Link-style name so the click target is obvious in the table. */}
          <span className="truncate text-primary underline decoration-primary/40 underline-offset-2 group-hover:decoration-primary">
            {name}
          </span>
          {/* P chip only when stamped; name stays clickable so Accept works after Reject. */}
          {memoryP ? (
            <span
              className="inline-flex shrink-0 items-center gap-1 rounded border border-emerald-600/50 bg-emerald-500/15 px-1 py-0.5 text-emerald-700 ring-emerald-600/20 group-hover:ring-2"
              title={pTitle}
            >
              <span className="text-[11px] font-bold leading-none">P</span>
              {memoryPDate ? (
                <span className="text-[10px] font-medium tabular-nums leading-none">
                  {memoryPDate}
                </span>
              ) : null}
            </span>
          ) : (
            <span className="shrink-0 text-[10px] font-medium text-primary/80 underline decoration-primary/40 underline-offset-2 group-hover:decoration-primary">
              Accept
            </span>
          )}
          <ChevronDown
            className="size-3 shrink-0 text-muted-foreground opacity-70 group-hover:opacity-100"
            aria-hidden
          />
        </button>
      </PopoverTrigger>
      <PopoverContent
        className="w-56 p-3"
        align="start"
        onClick={(event) => event.stopPropagation()}
      >
        <PopoverHeader className="mb-2 space-y-1">
          <PopoverTitle className="text-sm">Autocall memory</PopoverTitle>
          <PopoverDescription className="text-xs">
            {memoryP
              ? `${memoryPDate ? `P since ${memoryPDate}. ` : ""}Already tagged P — Reject clears until this name is +ive again on a future observation.`
              : "Not stamped. Accept marks P now, or wait for a future +ive observation check day."}
          </PopoverDescription>
        </PopoverHeader>
        <div className="flex items-center gap-2">
          {/* P already means accepted — only Reject when stamped; Accept only when not. */}
          {memoryP ? (
            <Button
              type="button"
              size="sm"
              variant="outline"
              className="h-7 w-full border-red-500/30 text-red-700 hover:bg-red-500/10"
              disabled={pending || !canAct}
              onClick={onReject}
            >
              <XCircle className="mr-1 size-3.5" strokeWidth={2.5} />
              Reject
            </Button>
          ) : (
            <Button
              type="button"
              size="sm"
              variant="outline"
              className="h-7 w-full border-emerald-500/30 text-emerald-700 hover:bg-emerald-500/10"
              disabled={pending || !canAct}
              onClick={onAccept}
            >
              <Check className="mr-1 size-3.5" strokeWidth={3} />
              Accept
            </Button>
          )}
        </div>
      </PopoverContent>
    </Popover>
  );
}

export const UNDERLYING_FIELDS = new Set<StructuredProductLegacyField>([
  "Industry",
  "Sector",
  "UnderlyingISIN1",
  "Underlying1",
  "InitialLevel",
  "StrikeLevel",
  "KOPrice",
  "BreakEvenPrice",
  "CMP",
  "away_from_Strike1",
  "away_from_Initial1",
]);

/** Collapse API group rows into one UI row per product (underlyings stack in-cell). */
export function groupStructuredProductRows(rows: StructuredProductReportRow[]) {
  const groups: StructuredProductReportRow[][] = [];
  let index = 0;
  while (index < rows.length) {
    const head = rows[index];
    const declaredSize = Math.max(1, Number(head.groupSize) || 1);
    if (declaredSize > 1 || head.isFirstInGroup) {
      const size = Math.min(declaredSize, rows.length - index);
      groups.push(rows.slice(index, index + size));
      index += size;
      continue;
    }

    // Fallback when groupSize is missing: fold consecutive legs of the same product.
    const productKey = head.productId || String(head.structureId) || head.id;
    let end = index + 1;
    while (end < rows.length) {
      const next = rows[end];
      const nextKey = next.productId || String(next.structureId) || next.id;
      if (nextKey !== productKey || next.isFirstInGroup || (Number(next.groupSize) || 1) > 1) {
        break;
      }
      end += 1;
    }
    groups.push(rows.slice(index, end));
    index = end;
  }
  return groups;
}

const TWO_DECIMAL_PERCENT_FIELDS = new Set<StructuredProductLegacyField>([
  "StrikePercentage",
  "KOBarrier",
  "Coupon",
  "away_from_Strike1",
  "away_from_Initial1",
  "profitApiPct",
]);

const TWO_DECIMAL_AMOUNT_FIELDS = new Set<StructuredProductLegacyField>([
  "IndicativeCoupon",
  "Notional",
  "InitialLevel",
  "StrikeLevel",
  "KOPrice",
  "BreakEvenPrice",
  "IndicativeAnnualCoupon",
  "annualCouponCalc",
  "MaxCoupon",
  "priceApi",
  "marketValueApi",
  "profitApi",
]);

export function isDcnStructuredProduct(row: StructuredProductReportRow): boolean {
  const candidates = [row.product.name, row.values.product_typeAbsolute];
  for (const candidate of candidates) {
    const plain = String(candidate ?? "")
      .replace(/<[^>]+>/g, " ")
      .trim()
      .toUpperCase();
    if (plain === "DCN" || plain.startsWith("DCN ")) {
      return true;
    }
  }
  return false;
}

export function reportCellValue(row: StructuredProductReportRow, field: StructuredProductLegacyField) {
  let value = row.values[field];
  if (field === "priceApi" || field === "marketValueApi" || field === "profitApi") {
    if (value === "" || value == null) return "—";
  }
  if (field === "annualCouponCalc") {
    if (value === "" || value == null) return "";
    if (String(value).trim() === "Error") return "Error";
  }
  if (field === "KOPrice" && (value === "" || value == null)) {
    value = row.ko_price;
  }
  if (field === "EarlyRedm" || field === "Delivery") {
    return Number(value) === 1 ? "1" : "0";
  }
  if (TWO_DECIMAL_PERCENT_FIELDS.has(field)) {
    const numeric = Number.parseFloat(String(value ?? "").replace(/[,%]/g, ""));
    return Number.isFinite(numeric) ? `${numeric.toFixed(2)}%` : "";
  }
  if (TWO_DECIMAL_AMOUNT_FIELDS.has(field)) {
    const numeric = Number.parseFloat(String(value ?? "").replace(/,/g, ""));
    return Number.isFinite(numeric)
      ? formatAmount(numeric, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
      : "";
  }
  return value === "" || value == null ? "" : String(value);
}

export function reportCellClass(row: StructuredProductReportRow, field: StructuredProductLegacyField) {
  if (field === "annualCouponCalc") {
    const value = String(row.values[field] ?? "").trim();
    if (value === "Error") return "font-medium text-red-600";
    return undefined;
  }
  if (field === "profitApi" || field === "profitApiPct") {
    const value = Number.parseFloat(String(row.values[field] ?? "").replace(/[,%]/g, ""));
    if (!Number.isFinite(value)) return "text-muted-foreground";
    return value < 0 ? "font-medium text-red-600" : "font-medium text-emerald-600";
  }
  if (field !== "away_from_Strike1" && field !== "away_from_Initial1") return undefined;
  const value = Number.parseFloat(String(row.values[field] ?? "").replace(/[,%]/g, ""));
  if (!Number.isFinite(value)) return "text-muted-foreground";
  return value < 0 ? "font-medium text-red-600" : "font-medium text-emerald-600";
}

export const RIGHT_ALIGNED_FIELDS = new Set<StructuredProductLegacyField>([
  "StrikePercentage",
  "KOBarrier",
  "Coupon",
  "IndicativeCoupon",
  "Notional",
  "InitialLevel",
  "StrikeLevel",
  "KOPrice",
  "BreakEvenPrice",
  "CMP",
  "priceApi",
  "marketValueApi",
  "profitApi",
  "profitApiPct",
  "away_from_Strike1",
  "away_from_Initial1",
  "IndicativeAnnualCoupon",
  "annualCouponCalc",
  "MaxCoupon",
]);

function FinalValuationBadge({ compact = false }: { compact?: boolean }) {
  return (
    <span
      className="shrink-0 rounded bg-amber-100 px-1.5 py-0.5 text-[10px] font-medium text-amber-800 dark:bg-amber-500/15 dark:text-amber-300"
      title="Final valuation date"
    >
      {compact ? "FVD" : "Final valuation"}
    </span>
  );
}

function NonCallBadge() {
  return (
    <span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground">
      non-call
    </span>
  );
}

function StructuredProductDateSeriesCell({
  series,
  label,
  showReceiptStatus = false,
}: {
  series: StructuredProductDateSeries;
  label: string;
  /** Coupon Dates: ✓ received / ✗ not received from Interest–Div ledger. */
  showReceiptStatus?: boolean;
}) {
  const hiddenCount = Math.max(0, series.all.length - series.visible.length);
  const hasNonCallDetails = series.all.some((item) => item.nonCall);
  const showPopover = hiddenCount > 0 || hasNonCallDetails || showReceiptStatus;

  const renderDateLine = (item: StructuredProductDateItem) => {
    const received = item.received === true;
    const pending = showReceiptStatus && item.received !== true;
    return (
      <div
        key={item.date}
        className={cn(
          "flex items-center gap-1.5 whitespace-nowrap text-xs leading-4",
          item.isPast && !showReceiptStatus && "text-muted-foreground",
        )}
      >
        {showReceiptStatus ? (
          <span
            className={cn(
              "shrink-0 font-bold tabular-nums",
              received ? "text-emerald-600" : "text-red-600",
            )}
            title={received ? "Interest received" : "Not received"}
            aria-label={received ? "Interest received" : "Not received"}
          >
            {received ? "✓" : "✗"}
          </span>
        ) : null}
        <span className={cn(pending && "text-muted-foreground")}>{item.formatted}</span>
        {item.isFinalValuation ? (
          <FinalValuationBadge compact />
        ) : item.nonCall ? (
          <NonCallBadge />
        ) : null}
      </div>
    );
  };

  return (
    <div className="flex items-start gap-1.5">
      <div className="min-w-0 space-y-0.5">
        {series.visible.map((item) => renderDateLine(item))}
      </div>
      {showPopover ? (
        <Popover>
          <PopoverTrigger asChild>
            <Button
              type="button"
              variant="ghost"
              size="sm"
              className="h-5 shrink-0 gap-1 px-1 text-blue-600 hover:bg-blue-50 hover:text-blue-700"
              aria-label={`View all ${label.toLowerCase()}`}
              onClick={(event) => event.stopPropagation()}
            >
              <Info className="size-3.5" strokeWidth={2.5} />
              {hiddenCount > 0 ? <span className="text-[10px] font-medium">+{hiddenCount}</span> : null}
            </Button>
          </PopoverTrigger>
          <PopoverContent align="start" side="bottom" className="w-72 p-0">
            <PopoverHeader className="border-b px-3 py-2">
              <PopoverTitle className="text-xs">{label}</PopoverTitle>
              <PopoverDescription className="text-[11px]">
                {series.all.length} {series.all.length === 1 ? "date" : "dates"}
                {showReceiptStatus ? " · ✓ received · ✗ not received" : ""}
              </PopoverDescription>
            </PopoverHeader>
            <div className="max-h-56 overflow-y-auto px-3 py-2">
              <div className="space-y-1">
                {series.all.map((item) => (
                  <div
                    key={item.date}
                    className="flex items-center justify-between gap-2 text-xs leading-4"
                  >
                    <div className="flex min-w-0 items-center gap-1.5">
                      {showReceiptStatus ? (
                        <span
                          className={cn(
                            "shrink-0 font-bold",
                            item.received ? "text-emerald-600" : "text-red-600",
                          )}
                        >
                          {item.received ? "✓" : "✗"}
                        </span>
                      ) : null}
                      <span className={cn(item.isPast && !showReceiptStatus && "text-muted-foreground")}>
                        {item.formatted}
                      </span>
                    </div>
                    {/* The final valuation date is never a call date, so its label replaces "non-call". */}
                    {item.isFinalValuation ? (
                      <FinalValuationBadge />
                    ) : item.nonCall ? (
                      <NonCallBadge />
                    ) : showReceiptStatus ? (
                      <span
                        className={cn(
                          "shrink-0 text-[10px]",
                          item.received ? "text-emerald-700" : "text-red-600",
                        )}
                      >
                        {item.received ? "received" : "not received"}
                      </span>
                    ) : null}
                  </div>
                ))}
              </div>
            </div>
          </PopoverContent>
        </Popover>
      ) : null}
    </div>
  );
}

export function StructuredProductCell({
  row,
  field,
}: {
  row: StructuredProductReportRow;
  field: StructuredProductLegacyField;
}) {
  if (field === "product_typeAbsolute") {
    const productLabel =
      mapStructureProductType(row.product.name || "") ||
      mapStructureProductType(String(reportCellValue(row, field) ?? "")) ||
      reportCellValue(row, field);

    return (
      <div className="leading-tight">
        <div className="font-medium">{productLabel}</div>
        {row.product.absoluteCoupon ? (
          <div className="mt-0.5 text-[11px] text-muted-foreground">
            Abs. coupon{" "}
            <span className="font-semibold text-emerald-600">
              {reportCellValue(row, "IndicativeCoupon")}
            </span>
          </div>
        ) : null}
        {row.product.phoenixTerms ? (
          <div className="mt-0.5 space-y-px text-[11px] text-muted-foreground">
            <div>
              Memory{" "}
              <span className="font-semibold text-emerald-600">
                {row.product.phoenixTerms.memory}
              </span>
            </div>
            {row.product.phoenixTerms.couponBarrier ? (
              <div>
                Coupon Barrier{" "}
                <span className="font-semibold text-emerald-600">
                  {row.product.phoenixTerms.couponBarrier}
                </span>
              </div>
            ) : null}
          </div>
        ) : null}
      </div>
    );
  }
  if (field === "Observationdates" || field === "CouponDates") {
    const series =
      field === "Observationdates" ? row.dates.observations : row.dates.coupons;
    return (
      <StructuredProductDateSeriesCell
        series={series}
        label={field === "Observationdates" ? "Observation dates" : "Coupon dates"}
        showReceiptStatus={field === "CouponDates"}
      />
    );
  }
  if (field === "NextObservationdate") {
    return row.dates.nextObservation?.formatted ?? "";
  }
  if (field === "UnderlyingISIN1" && row.underlyingMeta.currencyMismatch) {
    return (
      <span className="inline-flex items-center gap-1">
        {reportCellValue(row, field)}
        <TooltipProvider>
          <Tooltip>
            <TooltipTrigger asChild>
              <ArrowRightLeft
                className="size-3 cursor-help text-orange-500"
                onClick={(event) => event.stopPropagation()}
              />
            </TooltipTrigger>
            <TooltipContent>{row.underlyingMeta.currencyMismatchMessage}</TooltipContent>
          </Tooltip>
        </TooltipProvider>
      </span>
    );
  }
  return reportCellValue(row, field);
}
