"use client";

import { toastApiError } from "@/lib/toast-api-error";
import * as React from "react";
import { Building2, CircleDollarSign, Layers3 } from "lucide-react";
import { useFormContext, useWatch } from "react-hook-form";

import {
  fetchInterestDividendParentTransactionDetailClient,
  fetchInterestDividendSecurityPositionsClient,
  searchInterestDividendParentTransactionsClient,
  searchInterestDividendSecuritiesClient,
} from "@/app/customer/[tenant]/interest-dividend/_lib/interest-dividend-api";
import { type InterestDividendFormOptions } from "@/app/customer/[tenant]/interest-dividend/_lib/interest-dividend-form-options";
import {
  type InterestDividendFormValues,
  type ParentTransactionDetail,
  type SecurityPositionRow,
} from "@/app/customer/[tenant]/interest-dividend/_lib/interest-dividend-form-schema";
import { formGridClass, formSpanFull } from "@/components/form/common/form-layout";
import { DateField } from "@/components/form/fields/date-field";
import { NumberField } from "@/components/form/fields/number-field";
import { ReferenceLinkField } from "@/components/form/fields/reference-link-field";
import { SelectField } from "@/components/form/fields/select-field";
import { TextField } from "@/components/form/fields/text-field";
import { TransactionFormSection } from "@/components/form/transaction-workspace/form-section";
import { Input } from "@/components/ui/input";
import {
  formatDecimal,
  formatMoney,
  INTEREST_MODE_OPTIONS,
  toSelectOptions,
} from "./interest-dividend-form-utils";

/** Match Yii BaseActiveRecord::$decimal_precision (9) without truncating to 2 dp. */
function roundInterestAmount(value: number): number {
  if (!Number.isFinite(value)) return 0;
  return Number(value.toFixed(9));
}

function DetailRow({ label, value }: { label: string; value: string }) {
  if (!value) return null;

  return (
    <div className="grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)] gap-3 border-b border-border/40 py-2 last:border-b-0">
      <span className="font-medium text-foreground">{label}</span>
      <span className="text-muted-foreground">{value}</span>
    </div>
  );
}

function SummaryMetric({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg border border-border/50 bg-background/70 px-3 py-2">
      <p className="text-muted-foreground text-[11px] uppercase tracking-wider">{label}</p>
      <p className="mt-1 font-semibold text-sm">{value}</p>
    </div>
  );
}

function ParentTransactionDetailPanel({ detail }: { detail: ParentTransactionDetail }) {
  return (
    <div className="overflow-hidden rounded-xl border border-border/60 bg-card shadow-sm">
      <div className="border-b border-border/50 bg-muted/25 px-5 py-4">
        <p className="font-medium text-muted-foreground text-[11px] uppercase tracking-wider">Parent transaction</p>
        {detail.uid ? <p className="mt-1 font-mono text-sm">Ref. ID {detail.uid}</p> : null}
        {detail.f_type_label ? <p className="mt-1 text-muted-foreground text-xs">{detail.f_type_label}</p> : null}
      </div>
      <div className="px-5 py-3 text-sm">
        <DetailRow label="Security Name" value={detail.security_label} />
        <DetailRow label="Quantity" value={formatDecimal(detail.quantity)} />
        <DetailRow label="Currency (If Different)" value={detail.currency_label} />
        <DetailRow label="Price" value={formatDecimal(detail.price)} />
        <DetailRow label="Amount" value={formatDecimal(detail.amount)} />
      </div>
    </div>
  );
}

function LotMetric({ label, value, emphasize = false }: { label: string; value: string; emphasize?: boolean }) {
  return (
    <div className="min-w-0">
      <p className="text-muted-foreground text-[11px] uppercase tracking-wider">{label}</p>
      <p className={emphasize ? "mt-1 font-semibold text-sm tabular-nums" : "mt-1 font-medium text-sm tabular-nums"}>
        {value}
      </p>
    </div>
  );
}

function SecurityPositionsTable({
  rows,
  amountPerShare,
}: {
  rows: SecurityPositionRow[];
  amountPerShare: number;
}) {
  if (rows.length === 0) {
    return (
      <div className="rounded-lg border border-dashed border-border/70 bg-muted/20 px-4 py-8 text-center">
        <p className="font-medium text-sm">No linked lots yet</p>
        <p className="mt-1 text-muted-foreground text-sm">
          Select a security to load the positions included in this calculation.
        </p>
      </div>
    );
  }

  return (
    <ul className="space-y-3">
      {rows.map((row) => {
        const qty = Number(String(row.quantity).replace(/,/g, "")) || 0;
        const dividend = formatMoney(qty * amountPerShare);

        return (
          <li
            key={row.id}
            className="overflow-hidden rounded-lg border border-border/60 bg-background/70 shadow-xs"
          >
            <div className="flex flex-wrap items-start justify-between gap-3 border-b border-border/40 px-4 py-3 sm:px-5">
              <div className="min-w-0 space-y-1">
                <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
                  <p className="font-semibold text-sm tracking-tight">{row.f_type || "Position"}</p>
                  <span className="rounded-md border border-border/60 bg-muted/40 px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground">
                    Ref #{row.uid || "—"}
                  </span>
                </div>
                <p className="text-muted-foreground text-xs">
                  {[row.t_date, row.bank_name ? `Bank: ${row.bank_name}` : null].filter(Boolean).join(" · ") || "—"}
                </p>
              </div>
              <div className="text-right">
                <p className="text-muted-foreground text-[11px] uppercase tracking-wider">Quantity</p>
                <p className="mt-0.5 font-semibold text-base tabular-nums">{row.quantity || "—"}</p>
              </div>
            </div>

            <div className="grid grid-cols-2 gap-4 px-4 py-3 sm:grid-cols-4 sm:px-5">
              <LotMetric label="Purchased" value={String(row.purchased || "0.00")} />
              <LotMetric label="Sold" value={String(row.saled || "0.00")} />
              <LotMetric label="Price" value={String(row.price || "—")} />
              <LotMetric label="Dividend" value={dividend} emphasize />
            </div>
          </li>
        );
      })}
    </ul>
  );
}

export function InterestDividendFormBody({
  formOptions,
  enabledDate,
}: {
  formOptions: InterestDividendFormOptions;
  enabledDate: boolean;
}) {
  const form = useFormContext<InterestDividendFormValues>();
  const control = form.control;
  const watched = useWatch({ control });
  const [parentOptions, setParentOptions] = React.useState<Array<{ value: string; label: string }>>([]);
  const [parentSearchLoading, setParentSearchLoading] = React.useState(false);
  const [securityOptions, setSecurityOptions] = React.useState<Array<{ ticker: string; isin: string; label: string }>>(
    [],
  );
  const [positionRows, setPositionRows] = React.useState<SecurityPositionRow[]>([]);
  const [parentTransactionDetail, setParentTransactionDetail] = React.useState<ParentTransactionDetail | null>(null);
  const [parentDetailLoading, setParentDetailLoading] = React.useState(false);
  const [parentSearch, setParentSearch] = React.useState("");
  const [parentSearchActive, setParentSearchActive] = React.useState(false);
  const [securitySearch, setSecuritySearch] = React.useState("");

  const dType = watched.d_type ?? "1";
  const showCash = dType === "3";
  const showTransaction = dType === "1";
  const showSecurity = dType === "2";
  const showBank = enabledDate && (dType === "2" || dType === "3");

  const recalculateTotals = React.useCallback(() => {
    const quantity = Number(watched.quantity) || 0;
    const price = Number(watched.price) || 0;
    const commission = Number(watched.commission) || 0;
    const b1 = Number(watched.b_1) || 0;
    const b2 = Number(watched.b_2) || 0;
    // Legacy calculatetotal1: total = price * quantity for all d_type values.
    // Keep up to 9 decimals (Yii BaseActiveRecord::$decimal_precision) instead of toFixed(2).
    const amount = roundInterestAmount(quantity * price);
    const net = roundInterestAmount(amount - (commission + b1 + b2));
    form.setValue("amount", amount, { shouldDirty: true });
    form.setValue("net", net, { shouldDirty: true });
  }, [form, watched.b_1, watched.b_2, watched.commission, watched.price, watched.quantity]);

  React.useEffect(() => {
    recalculateTotals();
  }, [recalculateTotals]);

  const previousDTypeRef = React.useRef<string | null>(null);

  React.useEffect(() => {
    form.setValue("enabled_date", enabledDate);

    const previous = previousDTypeRef.current;
    previousDTypeRef.current = dType;

    // Legacy keeps md (Per Share / Total) for all types — do not force Total on Security/Cash.

    if (previous === null || previous === dType) {
      if (dType === "3" && previous === null) {
        // Don't wipe saved quantity on edit; only default cash qty when blank.
        const qty = Number(form.getValues("quantity"));
        if (!qty) form.setValue("quantity", 1);
      }
      return;
    }

    // Yii1 changeAmountTitle / setBlank: clear fields that no longer apply when type changes.
    setPositionRows([]);
    setParentTransactionDetail(null);
    setParentSearchActive(false);

    if (dType === "1") {
      form.setValue("quantity", 1);
      form.setValue("ticker", "");
      form.setValue("isin", "");
      form.setValue("security_label", "");
      form.setValue("bank_id", "");
      form.setValue("isin_pseudo", "");
      form.setValue("divident_children", []);
      setSecuritySearch("");
    } else if (dType === "2") {
      form.setValue("parent_id", "");
      form.setValue("parent_transaction_label", "");
      form.setValue("isin_pseudo", "");
      setParentSearch("");
    } else if (dType === "3") {
      form.setValue("quantity", 1);
      form.setValue("parent_id", "");
      form.setValue("parent_transaction_label", "");
      form.setValue("ticker", "");
      form.setValue("isin", "");
      form.setValue("security_label", "");
      form.setValue("divident_children", []);
      setParentSearch("");
      setSecuritySearch("");
    }
  }, [dType, enabledDate, form]);

  const loadSecurityPositions = React.useCallback(async () => {
    if (!showSecurity || !watched.ticker) {
      setPositionRows([]);
      form.setValue("divident_children", []);
      return;
    }

    const response = await fetchInterestDividendSecurityPositionsClient({
      id: watched.ticker,
      isin: watched.isin,
      date: watched.t_date,
      bank_id: watched.bank_id,
      enabled_date: enabledDate ? 1 : 0,
      real_quantity: form.getValues("quantity"),
      real_price: form.getValues("price"),
    });

    const payload = response.data;
    if (!payload || payload.status !== 1 || !Array.isArray(payload.rows)) {
      setPositionRows([]);
      form.setValue("divident_children", []);
      return;
    }

    const rows = payload.rows as SecurityPositionRow[];
    setPositionRows(rows);
    form.setValue(
      "divident_children",
      rows.map((row) => ({
        divident_id: Number(row.id),
        quantity: String(row.quantity),
      })),
    );
    // Keep saved quantity on edit; only adopt API quantity when blank/zero.
    const existingQty = Number(form.getValues("quantity")) || 0;
    if (!existingQty && payload.quantity != null && payload.quantity !== "") {
      form.setValue("quantity", Number(payload.quantity) || 1);
    }
    if (payload.bank && !form.getValues("bank_id")) {
      form.setValue("bank_id", String(payload.bank));
    }
    recalculateTotals();
  }, [
    enabledDate,
    form,
    recalculateTotals,
    showSecurity,
    watched.bank_id,
    watched.isin,
    watched.t_date,
    watched.ticker,
  ]);

  React.useEffect(() => {
    void loadSecurityPositions();
  }, [loadSecurityPositions]);

  React.useEffect(() => {
    const handle = window.setTimeout(async () => {
      if (!parentSearchActive || parentSearch.trim().length < 1) {
        setParentOptions([]);
        setParentSearchLoading(false);
        return;
      }
      setParentSearchLoading(true);
      try {
        const response = await searchInterestDividendParentTransactionsClient(parentSearch);
        const items = response.data?.items ?? [];
        setParentOptions(items.map((item) => ({ value: String(item.id), label: item.text })));
      } catch (error) {
        setParentOptions([]);
        toastApiError(error, "Failed to search parent transactions.");
      } finally {
        setParentSearchLoading(false);
      }
    }, 250);
    return () => window.clearTimeout(handle);
  }, [parentSearch, parentSearchActive]);

  React.useEffect(() => {
    const handle = window.setTimeout(async () => {
      if (securitySearch.trim().length < 1) {
        setSecurityOptions([]);
        return;
      }
      const response = await searchInterestDividendSecuritiesClient(securitySearch);
      setSecurityOptions(response.data?.items ?? []);
    }, 250);
    return () => window.clearTimeout(handle);
  }, [securitySearch]);

  React.useEffect(() => {
    if (dType !== "1") {
      setParentTransactionDetail(null);
    }
  }, [dType]);

  const loadParentTransactionDetail = React.useCallback(
    async (parentId: string, options?: { clearPrice?: boolean }) => {
      if (!parentId) {
        setParentTransactionDetail(null);
        return;
      }

      setParentDetailLoading(true);
      try {
        const response = await fetchInterestDividendParentTransactionDetailClient(parentId);
        const items = response.data?.items;
        if (response.data?.status === 1 && items) {
          setParentTransactionDetail(items);
          const nextLabel = [items.uid ? `Ref. ID ${items.uid}` : null, items.f_type_label || null]
            .filter(Boolean)
            .join(", ");
          if (nextLabel) {
            form.setValue("parent_transaction_label", nextLabel, { shouldDirty: false });
          }
          // Yii1 fetchVal: clear price for Interest on Transaction when user picks a parent
          if (options?.clearPrice) {
            form.setValue("price", 0, { shouldDirty: true });
          }
          if (items.quantity) {
            const quantity = Number(items.quantity) || 1;
            const currentQty = Number(form.getValues("quantity")) || 0;
            // Yii1 only overwrites quantity when the model quantity was empty on create
            if (options?.clearPrice || !currentQty) {
              form.setValue("quantity", quantity, { shouldDirty: true });
            }
          }
          const values = form.getValues();
          const quantity = Number(values.quantity) || 0;
          const price = Number(values.price) || 0;
          const commission = Number(values.commission) || 0;
          const b1 = Number(values.b_1) || 0;
          const b2 = Number(values.b_2) || 0;
          const amount = quantity * price;
          const net = amount - (commission + b1 + b2);
          form.setValue("amount", Number(amount.toFixed(2)), { shouldDirty: true });
          form.setValue("net", Number(net.toFixed(2)), { shouldDirty: true });
          return;
        }
        setParentTransactionDetail(null);
      } catch (error) {
        setParentTransactionDetail(null);
        toastApiError(error, "Failed to load parent transaction details.");
      } finally {
        setParentDetailLoading(false);
      }
    },
    [form],
  );

  React.useEffect(() => {
    if (!showTransaction || !watched.parent_id) {
      if (!showTransaction) setParentTransactionDetail(null);
      return;
    }
    void loadParentTransactionDetail(watched.parent_id, { clearPrice: false });
  }, [loadParentTransactionDetail, showTransaction, watched.parent_id]);

  const handleParentSelect = async (parentId: string, label: string) => {
    form.setValue("parent_id", parentId);
    form.setValue("parent_transaction_label", label);
    setParentSearch("");
    setParentSearchActive(false);
    setParentOptions([]);
    await loadParentTransactionDetail(parentId, { clearPrice: true });
  };

  return (
    <div className="space-y-6">
    <div className="grid gap-6 xl:grid-cols-[minmax(0,1fr)_22rem]">
      <div className="space-y-6">
        <TransactionFormSection
          title="Transaction details"
          description="Choose the payout source, link the trade or security, and capture banking references."
          icon={<Layers3 className="size-4" />}
        >
          <div className={formGridClass}>
            <DateField control={control} name="t_date" label="Placement Date" />
            <SelectField
              control={control}
              name="d_p"
              label="Transaction Type"
              options={toSelectOptions(formOptions.transactionCategories)}
            />
            <SelectField
              control={control}
              name="d_type"
              label="Type"
              options={toSelectOptions(formOptions.interestSourceTypes)}
            />

            {showCash ? (
              <TextField control={control} name="isin_pseudo" label="Security Ticker/ISIN" />
            ) : null}

            {showTransaction ? (
              <div className={formSpanFull}>
                <label className="mb-2 block font-medium text-sm">
                  Transaction Ref. # <span className="text-destructive">*</span>
                </label>
                <Input
                  value={parentSearch}
                  onChange={(event) => {
                    setParentSearchActive(true);
                    setParentSearch(event.target.value);
                  }}
                  onFocus={() => setParentSearchActive(true)}
                  placeholder="Search by Ref. ID, ticker, or ISIN…"
                />
                {parentSearchLoading ? (
                  <p className="mt-2 text-muted-foreground text-xs">Searching transactions…</p>
                ) : null}
                {parentSearchActive &&
                !parentSearchLoading &&
                parentSearch.trim().length > 0 &&
                parentOptions.length === 0 ? (
                  <p className="mt-2 text-muted-foreground text-xs">No matching transactions found.</p>
                ) : null}
                {parentOptions.length > 0 ? (
                  <div className="mt-3 overflow-hidden rounded-xl border border-border/60 bg-background/80 shadow-sm">
                    {parentOptions.map((option) => (
                      <button
                        key={option.value}
                        type="button"
                        className="block w-full border-b border-border/40 px-3 py-2.5 text-left text-sm transition-colors last:border-b-0 hover:bg-muted/50"
                        onClick={() => {
                          void handleParentSelect(option.value, option.label);
                        }}
                      >
                        <span className="line-clamp-2">{option.label}</span>
                      </button>
                    ))}
                  </div>
                ) : null}
                {watched.parent_id || watched.parent_transaction_label ? (
                  <div className="mt-3 rounded-lg border border-primary/15 bg-primary/5 px-3 py-2">
                    <p className="font-medium text-sm">
                      {watched.parent_transaction_label || `Selected transaction #${watched.parent_id}`}
                    </p>
                    {parentTransactionDetail?.f_type_label ? (
                      <p className="text-muted-foreground text-xs">{parentTransactionDetail.f_type_label}</p>
                    ) : null}
                  </div>
                ) : null}
                {form.formState.errors.parent_id ? (
                  <p className="mt-2 text-destructive text-sm">{form.formState.errors.parent_id.message}</p>
                ) : null}
              </div>
            ) : null}

            {showSecurity ? (
              <div className={formSpanFull}>
                <label className="mb-2 block font-medium text-sm">
                  Security Name / Security Ticker <span className="text-destructive">*</span>
                </label>
                <Input
                  value={securitySearch}
                  onChange={(event) => setSecuritySearch(event.target.value)}
                  placeholder="Search security…"
                />
                {securityOptions.length > 0 ? (
                  <div className="mt-3 overflow-hidden rounded-xl border border-border/60 bg-background/80 shadow-sm">
                    {securityOptions.map((option) => (
                      <button
                        key={`${option.ticker}-${option.isin}`}
                        type="button"
                        className="block w-full border-b border-border/40 px-3 py-2.5 text-left transition-colors last:border-b-0 hover:bg-muted/50"
                        onClick={() => {
                          form.setValue("ticker", option.ticker);
                          form.setValue("isin", option.isin);
                          form.setValue("security_label", option.label);
                          setSecuritySearch("");
                          setSecurityOptions([]);
                        }}
                      >
                        <div className="font-medium text-sm">{option.label}</div>
                        <div className="text-muted-foreground text-xs">
                          {option.ticker} {option.isin ? `· ${option.isin}` : ""}
                        </div>
                      </button>
                    ))}
                  </div>
                ) : null}
                {watched.ticker || watched.isin || watched.security_label ? (
                  <div className="mt-3 rounded-lg border border-primary/15 bg-primary/5 px-3 py-2">
                    <p className="font-medium text-sm">
                      {watched.security_label ||
                        [watched.ticker, watched.isin].filter(Boolean).join(" · ") ||
                        "Security selected"}
                    </p>
                    {watched.security_label && (watched.ticker || watched.isin) ? (
                      <p className="text-muted-foreground text-xs">
                        {[watched.ticker, watched.isin].filter(Boolean).join(" · ")}
                      </p>
                    ) : null}
                  </div>
                ) : null}
                {form.formState.errors.ticker || form.formState.errors.isin ? (
                  <p className="mt-2 text-destructive text-sm">
                    {form.formState.errors.ticker?.message || form.formState.errors.isin?.message}
                  </p>
                ) : null}
              </div>
            ) : null}

            <TextField control={control} name="r_no" label="Bank Advice Ref No." />

            {showBank ? (
              <SelectField
                control={control}
                name="bank_id"
                label={dType === "2" ? "Bank *" : "Bank"}
                options={toSelectOptions(formOptions.banks)}
                searchable
              />
            ) : null}
          </div>
        </TransactionFormSection>

        <TransactionFormSection
          title="Fees & amounts"
          description="Review share count, payout amount, tax, commission, and final net credit."
          icon={<CircleDollarSign className="size-4" />}
        >
          <div className={formGridClass}>
            <NumberField control={control} name="commission" label="Commission" min="0" step="0.01" />
            <NumberField control={control} name="b_1" label="Charges and fees abroad" min="0" step="0.01" />
            <NumberField control={control} name="b_2" label="Federal turnover tax" min="0" step="0.01" />
            <NumberField control={control} name="quantity" label="Quantity(No. Of Shares)" readOnly />
            <NumberField
              control={control}
              name="price"
              label={showTransaction ? "Amount" : "Amount per Share"}
              step="any"
            />
            <SelectField
              control={control}
              name="md"
              label="Interest Type"
              options={toSelectOptions([...INTEREST_MODE_OPTIONS])}
            />
            <NumberField control={control} name="amount" label="Total" readOnly />
            <div className={formSpanFull}>
              <ReferenceLinkField control={control} name="r_link" label="Reference Link" />
            </div>
          </div>
        </TransactionFormSection>
      </div>

      <aside className="space-y-4 xl:sticky xl:top-6 xl:self-start">
        {showTransaction && (parentDetailLoading || parentTransactionDetail) ? (
          parentDetailLoading ? (
            <div className="overflow-hidden rounded-xl border border-border/60 bg-card px-5 py-4 text-muted-foreground text-sm shadow-sm">
              Loading parent transaction…
            </div>
          ) : parentTransactionDetail ? (
            <ParentTransactionDetailPanel detail={parentTransactionDetail} />
          ) : null
        ) : null}

        <div className="overflow-hidden rounded-xl border border-border/60 bg-card shadow-sm">
          <div className="border-b border-border/50 bg-gradient-to-br from-primary/10 via-primary/5 to-transparent px-5 py-4">
            <p className="font-medium text-muted-foreground text-[11px] uppercase tracking-wider">Summary</p>
            <p className="mt-3 font-semibold text-2xl tracking-tight">{formatMoney(Number(watched.amount) || 0)}</p>
            <p className="mt-1 text-muted-foreground text-sm">Gross Amount</p>
          </div>
          <div className="grid gap-3 px-5 py-4">
            <SummaryMetric label="Commission" value={formatMoney(Number(watched.commission) || 0)} />
            <SummaryMetric label="Charges" value={formatMoney(Number(watched.b_1) || 0)} />
            <SummaryMetric label="Tax" value={formatMoney(Number(watched.b_2) || 0)} />
            <SummaryMetric label="Net Amount" value={formatMoney(Number(watched.net) || 0)} />
          </div>
        </div>
      </aside>
    </div>

      {showSecurity ? (
        <TransactionFormSection
          title="Linked lots"
          description="These positions are included in the dividend or interest calculation."
          icon={<Building2 className="size-4" />}
        >
          <SecurityPositionsTable rows={positionRows} amountPerShare={Number(watched.price) || 0} />
        </TransactionFormSection>
      ) : null}
    </div>
  );
}
