"use client";

import * as React from "react";

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

import type { FilterOption } from "@/app/customer/_lib/customer-asset-filter-options";
import {
  EMPTY_FX_ACCUMULATOR_FORM_OPTIONS,
  type FxAccumulatorFormOptions,
} from "@/app/customer/_lib/deposit-form-options";
import { stockFieldLabels, 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 { KnockAmountField } from "@/components/form/fields/knock-amount-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 { TextAreaField } from "@/components/form/fields/text-area-field";
import { TextField } from "@/components/form/fields/text-field";
import {
  defaultFxAccumulatorFormValues,
  fxAccumulatorTransactionFormSchema,
  type FxAccumulatorFormValues,
} from "@/components/form/schemas/fx-accumulator-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";

const DEFAULT_KNOCK_FT_OPTIONS = [
  { value: "1", label: "Knock In" },
  { value: "2", label: "Knock Out" },
];

export type LoadFxAccumulatorFormOptionsClient = () => Promise<{
  formOptions: FxAccumulatorFormOptions;
  defaults: Record<string, unknown> | null;
}>;

type FxAccumulatorTransactionFormProps = {
  formId: string;
  initialValues?: FxAccumulatorFormValues;
  onSubmit?: (values: FxAccumulatorFormValues) => void;
  loadFormOptions: LoadFxAccumulatorFormOptionsClient;
};

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

/** Yii1/Yii2: m_date = c_date + (duration - 1) * duration_other days. */
function calculateMaturityDate(cDate: string, duration: number, durationOther: string): string {
  const trimmed = cDate.trim();
  if (!trimmed || duration <= 0 || !durationOther.trim()) {
    return "";
  }

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

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

  const periods = Math.trunc(duration);
  for (let i = 1; i < periods; i += 1) {
    date.setDate(date.getDate() + 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 FxAccumulatorSummarySidebar() {
  const quantity = useWatch<FxAccumulatorFormValues, "quantity">({ name: "quantity" });
  const price = useWatch<FxAccumulatorFormValues, "price">({ name: "price" });
  const transaction = useWatch<FxAccumulatorFormValues, "transaction">({ name: "transaction" });
  const commission = useWatch<FxAccumulatorFormValues, "commission">({ name: "commission" });
  const b1 = useWatch<FxAccumulatorFormValues, "b_1">({ name: "b_1" });
  const b2 = useWatch<FxAccumulatorFormValues, "b_2">({ name: "b_2" });
  const mDate = useWatch<FxAccumulatorFormValues, "m_date">({ name: "m_date" });

  let gross = parseAmount(quantity) * parseAmount(price);
  if (String(transaction ?? "") === YII_TRANSACTION.purchase) {
    gross *= -1;
  }
  const fees = parseAmount(commission) + parseAmount(b1) + parseAmount(b2);
  // Yii1 FX Accumulator: net = amount + fees
  const net = gross + fees;

  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">Gross Exposure</span>
          <span className="font-mono">{formatMoney(gross)}</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>Net Exposure</span>
          <span className="font-mono">{formatMoney(net)}</span>
        </div>
      </div>
    </aside>
  );
}

export function FxAccumulatorTransactionForm({
  formId,
  initialValues,
  onSubmit,
  loadFormOptions,
}: FxAccumulatorTransactionFormProps) {
  const [formOptions, setFormOptions] = React.useState<FxAccumulatorFormOptions>(
    EMPTY_FX_ACCUMULATOR_FORM_OPTIONS,
  );
  const [optionsError, setOptionsError] = React.useState<string | null>(null);
  const [loadingOptions, setLoadingOptions] = React.useState(true);

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

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

  React.useEffect(() => {
    let cancelled = false;
    setLoadingOptions(true);
    void loadFormOptions()
      .then(({ formOptions: options, defaults }) => {
        if (cancelled) return;
        setFormOptions(options);
        if (!initialValues && defaults) {
          const patch: Partial<FxAccumulatorFormValues> = {};
          if (defaults.e_t != null) patch.execution_type = String(defaults.e_t);
          if (defaults.t_o_t != null) patch.transaction = String(defaults.t_o_t);
          if (defaults.duration_other != null) patch.duration_other = String(defaults.duration_other);
          if (Object.keys(patch).length > 0) {
            form.reset({ ...defaultFxAccumulatorFormValues, ...form.getValues(), ...patch });
          }
        }
      })
      .catch((error) => {
        if (!cancelled) {
          setOptionsError(error instanceof Error ? error.message : "Could not load form options.");
        }
      })
      .finally(() => {
        if (!cancelled) setLoadingOptions(false);
      });
    return () => {
      cancelled = true;
    };
  }, [form, initialValues, loadFormOptions]);

  const quantity = useWatch({ control: form.control, name: "quantity" });
  const price = useWatch({ control: form.control, name: "price" });
  const transaction = useWatch({ control: form.control, name: "transaction" });
  const cDate = useWatch({ control: form.control, name: "c_date" });
  const duration = useWatch({ control: form.control, name: "duration" });
  const durationOther = useWatch({ control: form.control, name: "duration_other" });

  React.useEffect(() => {
    let amount = Number(quantity || 0) * Number(price || 0);
    if (String(transaction ?? "") === YII_TRANSACTION.purchase) {
      amount *= -1;
    }
    form.setValue("amount", Number.isFinite(amount) ? amount : 0, { shouldDirty: true });
  }, [form, quantity, price, transaction]);

  React.useEffect(() => {
    const maturityDate = calculateMaturityDate(
      cDate ?? "",
      Number(duration || 0),
      String(durationOther ?? ""),
    );
    if (maturityDate) {
      form.setValue("m_date", maturityDate, { shouldDirty: true });
    }
  }, [form, cDate, duration, durationOther]);

  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="Security"
              description="ISIN/currency and parent security."
              icon={<Layers3 className="size-4" />}
              contentClassName={formGridClass}
            >
              <TextField control={form.control} name="ticker" label="ISIN/Currency" />
              <TextField control={form.control} name="isin" label="ISIN/Currency Name" />
              <TextField control={form.control} name="parent_isin" label="Parent ISIN" />
              <TextField control={form.control} name="parent_isin_name" label="Parent ISIN Name" />
            </TransactionFormSection>

            <TransactionFormSection
              title="Transaction"
              description="Dates, type, execution, and duration."
              icon={<ClipboardList className="size-4" />}
              contentClassName={formGridClass}
            >
              <DateField control={form.control} name="t_date" label="Placement Date" />
              <DateField control={form.control} name="o_date" label="Observation Date" />
              <SelectField
                control={form.control}
                name="transaction"
                label="Type of Transaction"
                options={toSelectOptions(formOptions.transactionTypes)}
                searchable
              />
              <SelectField
                control={form.control}
                name="execution_type"
                label={stockFieldLabels.execution_type}
                options={toSelectOptions(formOptions.executionTypes)}
                searchable
              />
              <TextField control={form.control} name="r_no" label={transactionFieldLabels.r_no} />
              <NumberField control={form.control} name="duration" label="No. of Periods" step="1" />
              <SelectField
                control={form.control}
                name="duration_other"
                label="Period unit"
                options={toSelectOptions(formOptions.timePeriods)}
              />
              <DateField control={form.control} name="c_date" label="Start Date" />
              <div className="hidden">
                <DateField control={form.control} name="m_date" label="Maturity Date" readOnly />
              </div>
            </TransactionFormSection>

            <TransactionFormSection
              title="Pricing"
              description="Quantity, strike, spot, and exposure."
              icon={<CircleDollarSign className="size-4" />}
              contentClassName={formGridClass}
            >
              <NumberField control={form.control} name="quantity" label="Quantity (Total)" step="0.0001" />
              <TextAreaField
                control={form.control}
                name="b_notes"
                label={transactionFieldLabels.b_notes}
                className={formSpanFull}
              />
              <NumberField control={form.control} name="price" label="Strike Price" step="0.0001" />
              <NumberField control={form.control} name="t_price" label="Spot Rate" step="0.0001" />
              <NumberField control={form.control} name="maturity" label="Profit Taking" step="0.0001" />
              <NumberField
                control={form.control}
                name="amount"
                label="Max Exposure"
                step="0.0001"
                readOnly
              />
              <NumberField control={form.control} name="commission" label="Commission" />
              <TextField control={form.control} name="b_1" label="Charges" />
              <TextField control={form.control} name="b_2" label="Tax" />
              <SelectField
                control={form.control}
                name="c_currency"
                label="Exchange Currency (If applicable)"
                options={toSelectOptions(formOptions.exchangeCurrencies)}
                searchable
              />
            </TransactionFormSection>

            <TransactionFormSection
              title="Bank & knock"
              description="Bank, relationship manager, attachment, and knock."
              icon={<Building2 className="size-4" />}
              contentClassName={formGridClass}
            >
              <SelectField
                control={form.control}
                name="bank"
                label={transactionFieldLabels.bank}
                options={toSelectOptions(formOptions.banks)}
                searchable
              />
              <TextField control={form.control} name="r_m" label={transactionFieldLabels.r_m} />
              <ReferenceLinkField control={form.control} name="r_link" />
              <KnockAmountField
                control={form.control}
                knockFtName="knock_ft"
                knockName="knock"
                knockTName="knock_t"
                knockFtOptions={DEFAULT_KNOCK_FT_OPTIONS}
              />
            </TransactionFormSection>
          </div>

          <FxAccumulatorSummarySidebar />
        </div>
      </form>
    </FormProvider>
  );
}
