"use client";

import * as React from "react";

import { zodResolver } from "@hookform/resolvers/zod";
import { Building2, CircleDollarSign, ClipboardList, StickyNote } from "lucide-react";
import { FormProvider, useForm, useWatch } from "react-hook-form";

import type { FilterOption } from "@/app/customer/_lib/customer-asset-filter-options";
import {
  EMPTY_DEPOSIT_FORM_OPTIONS,
  type DepositFormOptions,
} from "@/app/customer/_lib/deposit-form-options";
import { transactionFieldLabels } from "@/components/form/common/field-labels";
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 { SelectField } from "@/components/form/fields/select-field";
import { TextAreaField } from "@/components/form/fields/text-area-field";
import { TextField } from "@/components/form/fields/text-field";
import {
  buildDepositTransactionFormSchema,
  defaultDepositFormValues,
  defaultLeverageFormValues,
  type DepositFormValues,
} from "@/components/form/schemas/deposit-transaction-schema";
import { YII_TRANSACTION } from "@/config/yii-transaction";
import { formatMoney, parseAmount } from "@/components/form/transaction-workspace/transaction-form-summary";

import { TransactionFormSection } from "./form-section";

export type DepositFormVariant = "fixed-deposit" | "leverage";

export type LoadDepositFormOptionsClient = (aClass?: string) => Promise<{
  formOptions: DepositFormOptions;
  defaults: Record<string, unknown> | null;
}>;

type DepositTransactionFormProps = {
  formId: string;
  variant?: DepositFormVariant;
  initialValues?: DepositFormValues;
  onSubmit?: (values: DepositFormValues) => void;
  loadFormOptions: LoadDepositFormOptionsClient;
};

function toSelectOptions(options: FilterOption[]) {
  return options.map((option) => ({ value: option.value, label: option.label }));
}

function resolveDefaults(variant: DepositFormVariant) {
  return variant === "leverage" ? defaultLeverageFormValues : defaultDepositFormValues;
}

/** Yii1 leverage/deposit maturity: t_date + (duration * duration_other) days; sale uses t_date. */
function calculateLeverageMaturityDate(
  placementDate: string,
  duration: number,
  durationOther: string,
  isSale: boolean,
): string {
  const trimmed = placementDate.trim();
  if (!trimmed) return "";

  if (isSale) {
    return trimmed;
  }

  const unitDays = Number.parseInt(durationOther, 10);
  if (!Number.isFinite(duration) || duration <= 0 || !Number.isFinite(unitDays) || unitDays <= 0) {
    return "";
  }

  const date = new Date(`${trimmed}T00:00:00`);
  if (Number.isNaN(date.getTime())) {
    return "";
  }

  date.setDate(date.getDate() + Math.trunc(duration) * unitDays);
  const year = date.getFullYear();
  const month = `${date.getMonth() + 1}`.padStart(2, "0");
  const day = `${date.getDate()}`.padStart(2, "0");
  return `${year}-${month}-${day}`;
}

function DepositSummarySidebar({ formOptions }: { formOptions: DepositFormOptions }) {
  const price = useWatch<DepositFormValues, "price">({ name: "price" });
  const commission = useWatch<DepositFormValues, "commission">({ name: "commission" });
  const b1 = useWatch<DepositFormValues, "b_1">({ name: "b_1" });
  const b2 = useWatch<DepositFormValues, "b_2">({ name: "b_2" });
  const iRate = useWatch<DepositFormValues, "i_rate">({ name: "i_rate" });
  const totalDays = useWatch<DepositFormValues, "total_days">({ name: "total_days" });
  const mDate = useWatch<DepositFormValues, "m_date">({ name: "m_date" });
  const currency = useWatch<DepositFormValues, "p_currency">({ name: "p_currency" });
  const transaction = useWatch<DepositFormValues, "transaction">({ name: "transaction" });

  // Yii1: purchase (1453) stores/uses negative amount; sale (1473) positive.
  const amount =
    String(transaction ?? YII_TRANSACTION.purchase) === YII_TRANSACTION.sale
      ? Math.abs(parseAmount(price))
      : -Math.abs(parseAmount(price));
  const interest =
    parseAmount(iRate) && parseAmount(totalDays) && amount
      ? (amount * parseAmount(totalDays) * (parseAmount(iRate) / 100)) / 365
      : 0;
  const net =
    amount + interest - (parseAmount(commission) + parseAmount(b1) + parseAmount(b2));

  const currencyLabel =
    formOptions.currencies.find((option) => option.value === currency)?.label ?? currency;

  return (
    <aside className="flex h-fit flex-col gap-4 rounded-xl border border-border/60 bg-muted/20 p-4 lg:sticky lg:top-4">
      <p className="font-medium text-sm">Live summary</p>
      <div className="space-y-2 text-sm">
        <div className="flex justify-between gap-3">
          <span className="text-muted-foreground">Amount</span>
          <span className="font-mono">{formatMoney(amount)}</span>
        </div>
        <div className="flex justify-between gap-3">
          <span className="text-muted-foreground">Commission</span>
          <span className="font-mono">{formatMoney(parseAmount(commission))}</span>
        </div>
        <div className="flex justify-between gap-3">
          <span className="text-muted-foreground">Charges</span>
          <span className="font-mono">{formatMoney(parseAmount(b1))}</span>
        </div>
        <div className="flex justify-between gap-3">
          <span className="text-muted-foreground">Tax</span>
          <span className="font-mono">{formatMoney(parseAmount(b2))}</span>
        </div>
        <div className="flex justify-between gap-3">
          <span className="text-muted-foreground">Maturity date</span>
          <span>{mDate || "—"}</span>
        </div>
        <div className="flex justify-between gap-3 border-t border-border/50 pt-2 font-medium">
          <span>Amount at maturity</span>
          <span className="font-mono">
            {currencyLabel ? `${currencyLabel} ` : ""}
            {formatMoney(net)}
          </span>
        </div>
      </div>
    </aside>
  );
}

export function DepositTransactionForm({
  formId,
  variant = "fixed-deposit",
  initialValues,
  onSubmit,
  loadFormOptions,
}: DepositTransactionFormProps) {
  const [formOptions, setFormOptions] = React.useState<DepositFormOptions>(EMPTY_DEPOSIT_FORM_OPTIONS);
  const [optionsError, setOptionsError] = React.useState<string | null>(null);
  const [loadingOptions, setLoadingOptions] = React.useState(true);
  const defaultValues = React.useMemo(() => resolveDefaults(variant), [variant]);
  const resolver = React.useMemo(
    () => zodResolver(buildDepositTransactionFormSchema(variant)),
    [variant],
  );

  const form = useForm<DepositFormValues>({
    resolver,
    defaultValues: { ...defaultValues, ...initialValues },
    mode: "onBlur",
  });

  React.useEffect(() => {
    form.reset({ ...defaultValues, ...initialValues });
  }, [form, initialValues, defaultValues]);

  React.useEffect(() => {
    let cancelled = false;
    setLoadingOptions(true);
    setOptionsError(null);

    void loadFormOptions()
      .then(({ formOptions: options, defaults }) => {
        if (cancelled) return;
        setFormOptions(options);
        if (!initialValues) {
          const patch: Partial<DepositFormValues> = {};
          if (defaults?.a_class != null) patch.a_class = String(defaults.a_class);
          if (defaults?.a_type != null) patch.a_type = String(defaults.a_type);
          if (defaults?.t_o_t != null) patch.transaction = String(defaults.t_o_t);
          if (defaults?.i_b != null) patch.i_b = String(defaults.i_b);
          if (Object.keys(patch).length > 0) {
            form.reset({ ...defaultValues, ...form.getValues(), ...patch });
          }
        }
      })
      .catch((error) => {
        if (cancelled) return;
        setOptionsError(error instanceof Error ? error.message : "Could not load form options.");
      })
      .finally(() => {
        if (!cancelled) setLoadingOptions(false);
      });

    return () => {
      cancelled = true;
    };
  }, [form, initialValues, loadFormOptions, defaultValues]);

  const price = useWatch({ control: form.control, name: "price" });
  const parentId = useWatch({ control: form.control, name: "parent_id" });
  const transaction = useWatch({ control: form.control, name: "transaction" });
  const tDate = useWatch({ control: form.control, name: "t_date" });
  const duration = useWatch({ control: form.control, name: "duration" });
  const durationOther = useWatch({ control: form.control, name: "duration_other" });
  const isLeverageSale =
    variant === "leverage" &&
    (Boolean(String(parentId ?? "").trim()) || String(transaction ?? "") === YII_TRANSACTION.sale);

  React.useEffect(() => {
    // Yii1 beforeSave: purchase (1453) stores negative amount; sale (1473) stores positive.
    const signedAmount =
      String(transaction ?? YII_TRANSACTION.purchase) === YII_TRANSACTION.sale
        ? Math.abs(parseAmount(price))
        : -Math.abs(parseAmount(price));
    form.setValue("amount", signedAmount, { shouldDirty: true });
  }, [form, price, transaction]);

  React.useEffect(() => {
    if (variant !== "leverage") return;
    const maturity = calculateLeverageMaturityDate(
      tDate ?? "",
      Number(duration || 0),
      String(durationOther ?? ""),
      isLeverageSale,
    );
    if (maturity) {
      form.setValue("m_date", maturity, { shouldDirty: true });
    }
    const unitDays = Number.parseInt(String(durationOther ?? ""), 10);
    if (Number.isFinite(unitDays) && unitDays > 0 && Number(duration) > 0) {
      form.setValue("total_days", Math.trunc(Number(duration)) * unitDays, { shouldDirty: true });
    }
  }, [form, variant, tDate, duration, durationOther, isLeverageSale]);

  const amountLabel =
    variant === "leverage" ? "Amount" : "Deposit Amount";

  return (
    <FormProvider {...form}>
      <form
        id={formId}
        noValidate
        onSubmit={form.handleSubmit((values) => onSubmit?.(values))}
        className="w-full min-w-0"
      >
        {loadingOptions ? (
          <p className="mb-4 text-muted-foreground text-sm">Loading dropdown options…</p>
        ) : null}
        {optionsError ? <p className="mb-4 text-destructive text-sm">{optionsError}</p> : null}

        <div className="grid w-full min-w-0 grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_18rem] xl:gap-8">
          <div className="flex min-w-0 flex-col gap-5 lg:gap-6">
            <TransactionFormSection
              title="Deposit details"
              description="Currency, amount, duration, placement date, and interest."
              icon={<ClipboardList className="size-4" />}
              contentClassName={formGridClass}
            >
              <SelectField
                control={form.control}
                name="p_currency"
                label={transactionFieldLabels.p_currency}
                options={toSelectOptions(formOptions.currencies)}
                disabled={isLeverageSale}
                searchable
                searchPlaceholder="Search currency…"
              />
              <NumberField
                control={form.control}
                name="price"
                label={amountLabel}
                step="0.01"
                readOnly={isLeverageSale}
              />
              <NumberField
                control={form.control}
                name="duration"
                label="Time Period"
                step="1"
                readOnly={isLeverageSale}
              />
              <SelectField
                control={form.control}
                name="duration_other"
                label="Period unit"
                options={toSelectOptions(formOptions.timePeriods)}
                disabled={isLeverageSale}
              />
              <DateField control={form.control} name="t_date" label="Placement Date" />
              <TextField control={form.control} name="r_no" label={transactionFieldLabels.r_no} />
              <NumberField
                control={form.control}
                name="i_rate"
                label="Interest Rate (% p.a.)"
                step="0.0001"
                readOnly={isLeverageSale}
              />
              {variant === "leverage" ? (
                <div className="hidden">
                  <DateField control={form.control} name="m_date" label="Maturity Date" readOnly />
                </div>
              ) : (
                <DateField control={form.control} name="m_date" label="Maturity Date" />
              )}
              {/* Yii1 cash_deposit/_frm: i_b is d-none — keep in form state for API defaults. */}
              <div className="hidden">
                <SelectField
                  control={form.control}
                  name="i_b"
                  label="Interest Rate Base"
                  options={toSelectOptions(formOptions.interestBase)}
                />
              </div>
              <SelectField
                control={form.control}
                name="bank"
                label={transactionFieldLabels.bank}
                options={toSelectOptions(formOptions.banks)}
                disabled={isLeverageSale}
                searchable
                searchPlaceholder="Search bank…"
              />
            </TransactionFormSection>

            <TransactionFormSection
              title="Fees"
              description="Transaction costs, premiums, and tax."
              icon={<CircleDollarSign className="size-4" />}
              contentClassName={formGridClass}
            >
              <NumberField control={form.control} name="commission" label="Transaction Costs" />
              <TextField control={form.control} name="b_1" label="Premium" />
              <TextField control={form.control} name="b_2" label="Tax" />
            </TransactionFormSection>

            <TransactionFormSection
              title={variant === "leverage" ? "Attachment" : "Classification"}
              description={
                variant === "leverage"
                  ? "Reference file link."
                  : "Internal asset classification (defaults applied)."
              }
              icon={variant === "leverage" ? <StickyNote className="size-4" /> : <Building2 className="size-4" />}
              contentClassName={variant === "leverage" ? undefined : formGridClass}
            >
              <div className="hidden">
                <SelectField
                  control={form.control}
                  name="a_class"
                  label={transactionFieldLabels.a_class}
                  options={toSelectOptions(formOptions.assetClasses)}
                />
                <SelectField
                  control={form.control}
                  name="a_type"
                  label={transactionFieldLabels.a_type}
                  options={toSelectOptions(formOptions.assetTypes)}
                />
              </div>
              <TextField
                control={form.control}
                name="r_link"
                label={transactionFieldLabels.r_link}
                className={variant === "leverage" ? formSpanFull : undefined}
              />
            </TransactionFormSection>

            <TransactionFormSection
              title="Notes"
              description="Remarks and purpose."
              icon={<StickyNote className="size-4" />}
              contentClassName={formGridClass}
            >
              <TextAreaField
                control={form.control}
                name="remarks"
                label={transactionFieldLabels.remarks}
                className={formSpanFull}
              />
              <TextAreaField
                control={form.control}
                name="purpose"
                label={transactionFieldLabels.purpose}
                className={formSpanFull}
              />
            </TransactionFormSection>
          </div>

          <DepositSummarySidebar formOptions={formOptions} />
        </div>
      </form>
    </FormProvider>
  );
}
