"use client";

import * as React from "react";

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

import type { FilterOption } from "@/app/customer/_lib/customer-asset-filter-options";
import { withServerValidationErrors } from "@/app/customer/_lib/apply-yii-validation-errors";
import { loadStockFormOptionsClient } from "@/app/customer/[tenant]/stock/_lib/stock-api";
import type { LoadStockFormOptionsClient } from "@/app/customer/[tenant]/stock/_lib/stock-api";
import type { StockChildFieldMeta } from "@/app/customer/[tenant]/stock/_lib/stock-child-types";
import {
  EMPTY_STOCK_FORM_OPTIONS,
  mapStockFormOptions,
  type StockFormOptions,
} from "@/app/customer/[tenant]/stock/_lib/stock-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 { 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 {
  defaultModuleTransactionValues,
  moduleTransactionFormSchema,
  type ModuleTransactionFormValues,
} from "@/components/form/schemas/module-transaction-schema";
import {
  cryptoTransactionFormSchema,
  defaultCryptoTransactionValues,
  defaultMixedFundTransactionValues,
  defaultOtherAssetsTransactionValues,
  otherAssetsTransactionFormSchema,
  type CryptoFormValues,
  type OtherAssetsFormValues,
} from "@/components/form/schemas/extended-stock-transaction-schema";
import type { CommonTransactionFormValues } from "@/components/form/schemas/transaction-schema";

import { TransactionFormSection } from "./form-section";
import {
  PURCHASE_TRANSACTION_TYPE,
  TransactionAmountSummarySidebar,
} from "./transaction-form-summary";

const MATURITY_EXECUTION_TYPE = "1477";
const OTHER_TRANSACTION_TYPE = "1524";

export type StockTransactionFormVariant =
  | "stock"
  | "stock-funds"
  | "mixed-funds"
  | "crypto"
  | "other-assets"
  | "commodity";

type StockFormValues =
  | ModuleTransactionFormValues
  | CryptoFormValues
  | OtherAssetsFormValues;

type StockTransactionFormProps = {
  formId: string;
  variant?: StockTransactionFormVariant;
  initialValues?: StockFormValues;
  onSubmit?: (values: StockFormValues) => void | Promise<void>;
  loadFormOptions?: LoadStockFormOptionsClient;
  fieldMeta?: StockChildFieldMeta;
  formOptionsRaw?: Record<string, Record<string, string>>;
};

function LockedSection({
  locked,
  children,
}: {
  locked: boolean;
  children: React.ReactNode;
}) {
  if (!locked) {
    return <>{children}</>;
  }

  return (
    <div className="relative">
      <div
        className="pointer-events-none absolute inset-0 z-10 rounded-lg bg-background/40"
        aria-hidden
      />
      {children}
    </div>
  );
}

function resolveDefaultValues(
  variant: StockTransactionFormVariant,
): StockFormValues {
  switch (variant) {
    case "crypto":
      return defaultCryptoTransactionValues;
    case "other-assets":
      return defaultOtherAssetsTransactionValues;
    case "mixed-funds":
      return defaultMixedFundTransactionValues;
    case "commodity":
      return { ...defaultModuleTransactionValues, a_class: "1432" };
    default:
      return defaultModuleTransactionValues;
  }
}

function resolveFormSchema(variant: StockTransactionFormVariant) {
  switch (variant) {
    case "crypto":
      return cryptoTransactionFormSchema;
    case "other-assets":
      return otherAssetsTransactionFormSchema;
    default:
      return moduleTransactionFormSchema;
  }
}

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

function AssetClassWatcher({
  onChange,
}: {
  onChange: (assetClassId: string) => void;
}) {
  const { control } = useFormContext<ModuleTransactionFormValues>();
  const aClass = useWatch({ control, name: "a_class" });
  const previous = React.useRef<string | null>(null);

  React.useEffect(() => {
    const next = aClass?.trim() || "";
    if (!next || previous.current === next) return;
    previous.current = next;
    onChange(next);
  }, [aClass, onChange]);

  return null;
}

export function StockTransactionForm({
  formId,
  variant = "stock",
  initialValues,
  onSubmit,
  loadFormOptions = loadStockFormOptionsClient,
  fieldMeta,
  formOptionsRaw,
}: StockTransactionFormProps) {
  const [formOptions, setFormOptions] = React.useState<StockFormOptions>(
    EMPTY_STOCK_FORM_OPTIONS,
  );
  const [optionsError, setOptionsError] = React.useState<string | null>(null);
  const [loadingOptions, setLoadingOptions] = React.useState(true);
  const defaultValues = React.useMemo(
    () => resolveDefaultValues(variant),
    [variant],
  );
  const formSchema = React.useMemo(() => resolveFormSchema(variant), [variant]);
  const showAssetType = variant !== "other-assets";
  const showMarketPrice = variant === "crypto" || variant === "other-assets";
  const showAssetTypeText = variant === "other-assets";

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

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

  const hideTransactionField =
    fieldMeta?.hiddenFields.includes("transaction") ?? false;
  const lockParentSection = fieldMeta?.lockParentSection ?? false;

  React.useEffect(() => {
    if (formOptionsRaw) {
      setFormOptions(mapStockFormOptions(formOptionsRaw));
      setLoadingOptions(false);
      setOptionsError(null);
      return;
    }

    let cancelled = false;
    setLoadingOptions(true);
    setOptionsError(null);

    void loadFormOptions()
      .then(({ formOptions: options, defaults }) => {
        if (cancelled) return;
        setFormOptions(options);
        if (!initialValues) {
          const patch: Partial<StockFormValues> = {};
          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?.e_t != null && !form.getValues("execution_type")) {
            patch.execution_type = String(defaults.e_t);
          }
          if (defaults?.t_o_t != null && !form.getValues("transaction")) {
            patch.transaction = String(defaults.t_o_t);
          }
          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, formOptionsRaw]);

  const commonControl =
    form.control as unknown as Control<CommonTransactionFormValues>;
  const executionType = useWatch({
    control: form.control,
    name: "execution_type",
  });
  const transaction = useWatch({ control: form.control, name: "transaction" });
  const quantity = useWatch({ control: form.control, name: "quantity" });
  const price = useWatch({ control: form.control, name: "price" });
  const showMaturityDate = executionType === MATURITY_EXECUTION_TYPE;
  const showTransactionOther = transaction === OTHER_TRANSACTION_TYPE;
  const amountLabel =
    executionType === MATURITY_EXECUTION_TYPE
      ? "Max Exposure"
      : transactionFieldLabels.amount;

  // Yii1 Stock::beforeSave: amount = quantity * price; purchase (1453) → negate.
  React.useEffect(() => {
    const qty = Number(quantity || 0);
    const px = Number(price || 0);
    let amount = qty * px;
    if (String(transaction ?? "") === PURCHASE_TRANSACTION_TYPE) {
      amount = -Math.abs(amount);
    }
    form.setValue(
      "amount",
      Number.isFinite(amount) ? Number(amount.toFixed(8)) : 0,
      {
        shouldValidate: false,
        shouldDirty: false,
      },
    );
  }, [form, quantity, price, transaction]);

  const reloadAssetTypes = React.useCallback(
    async (assetClassId: string) => {
      try {
        const { formOptions: next } = await loadFormOptions(assetClassId);
        setFormOptions((prev) => ({
          ...prev,
          assetTypes: next.assetTypes,
          assetClasses: next.assetClasses.length
            ? next.assetClasses
            : prev.assetClasses,
        }));
      } catch {
        // Keep existing options if refresh fails.
      }
    },
    [loadFormOptions],
  );

  return (
    <FormProvider {...form}>
      <form
        id={formId}
        noValidate
        onSubmit={form.handleSubmit(
          withServerValidationErrors(form.setError, onSubmit),
        )}
        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">
            {hideTransactionField && lockParentSection ? (
              <LockedSection locked>
                <TransactionFormSection
                  title="Parent stock"
                  icon={<Layers3 className="size-4" />}
                  contentClassName={formGridClass}
                >
                  <TextField
                    control={commonControl}
                    name="uid"
                    label="Ref. ID"
                  />
                </TransactionFormSection>
              </LockedSection>
            ) : null}

            <TransactionFormSection
              title="Transaction & order"
              description="Trade date, type of transaction, execution, reference, and quantity."
              icon={<ClipboardList className="size-4" />}
              contentClassName={formGridClass}
            >
              <DateField
                control={commonControl}
                name="t_date"
                label={transactionFieldLabels.t_date}
              />
              {hideTransactionField ? null : (
                <SelectField
                  control={form.control}
                  name="transaction"
                  label={stockFieldLabels.transaction}
                  options={toSelectOptions(formOptions.transactionTypes)}
                  searchable
                  searchPlaceholder="Search transaction type…"
                />
              )}
              {showTransactionOther ? (
                <TextField
                  control={form.control}
                  name="t_o_t_other"
                  label={stockFieldLabels.t_o_t_other}
                />
              ) : null}
              <SelectField
                control={form.control}
                name="execution_type"
                label={stockFieldLabels.execution_type}
                options={toSelectOptions(formOptions.executionTypes)}
                searchable
                searchPlaceholder="Search execution type…"
              />
              <TextField
                control={commonControl}
                name="r_no"
                label={transactionFieldLabels.r_no}
              />
              <NumberField
                control={commonControl}
                name="quantity"
                label={transactionFieldLabels.quantity}
                step="0.0001"
              />
              {showMaturityDate ? (
                <DateField
                  control={form.control}
                  name="m_date"
                  label={transactionFieldLabels.m_date}
                />
              ) : null}
            </TransactionFormSection>

            <TransactionFormSection
              title="Security & pricing"
              description="Ticker, ISIN, price, effective date, and bank notes."
              icon={<Layers3 className="size-4" />}
              contentClassName={formGridClass}
            >
              <TextField
                control={commonControl}
                name="ticker"
                label={transactionFieldLabels.ticker}
              />
              <TextField
                control={commonControl}
                name="isin"
                label={transactionFieldLabels.isin}
              />
              <NumberField
                control={commonControl}
                name="price"
                label={transactionFieldLabels.price}
              />
              <DateField
                control={commonControl}
                name="p_date"
                label={transactionFieldLabels.p_date}
              />
              <NumberField
                control={commonControl}
                name="amount"
                label={amountLabel}
                readOnly
                min="-999999999999"
                step="0.0001"
              />
              <NumberField
                control={commonControl}
                name="t_price"
                label={transactionFieldLabels.t_price}
              />
              <TextAreaField
                control={commonControl}
                name="b_notes"
                label={transactionFieldLabels.b_notes}
                className={formSpanFull}
              />
            </TransactionFormSection>

            <TransactionFormSection
              title="Fees & currency"
              description="Commission, charges, tax, and settlement currency."
              icon={<CircleDollarSign className="size-4" />}
              contentClassName={formGridClass}
            >
              <NumberField
                control={commonControl}
                name="commission"
                label={transactionFieldLabels.commission}
              />
              <TextField
                control={commonControl}
                name="b_1"
                label={transactionFieldLabels.b_1}
              />
              <TextField
                control={commonControl}
                name="b_2"
                label={transactionFieldLabels.b_2}
              />
              <SelectField
                control={commonControl}
                name="p_currency"
                label={transactionFieldLabels.p_currency}
                options={toSelectOptions(formOptions.currencies)}
                searchable
                searchPlaceholder="Search currency…"
              />
            </TransactionFormSection>

            <TransactionFormSection
              title="Classification & bank"
              description="Asset type, bank holder, and relationship details."
              icon={<Building2 className="size-4" />}
              contentClassName={formGridClass}
            >
              <div className="hidden">
                <SelectField
                  control={commonControl}
                  name="a_class"
                  label={transactionFieldLabels.a_class}
                  options={toSelectOptions(formOptions.assetClasses)}
                />
              </div>
              {showAssetType ? (
                <SelectField
                  control={commonControl}
                  name="a_type"
                  label={transactionFieldLabels.a_type}
                  options={toSelectOptions(formOptions.assetTypes)}
                  searchable
                  searchPlaceholder="Search asset type…"
                />
              ) : null}
              <SelectField
                control={commonControl}
                name="bank"
                label={transactionFieldLabels.bank}
                options={toSelectOptions(formOptions.banks)}
                searchable
                searchPlaceholder="Search bank…"
              />
              {showAssetTypeText ? (
                <TextField
                  control={form.control}
                  name="asset_type_t"
                  label={transactionFieldLabels.asset_type_t}
                />
              ) : null}
              {showMarketPrice ? (
                <NumberField
                  control={form.control}
                  name="market_price_t"
                  label={transactionFieldLabels.market_price_t}
                  step="0.0001"
                />
              ) : null}
              <TextField
                control={commonControl}
                name="r_m"
                label={transactionFieldLabels.r_m}
              />
              <TextField
                control={commonControl}
                name="r_link"
                label={transactionFieldLabels.r_link}
              />
            </TransactionFormSection>

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

            <AssetClassWatcher onChange={reloadAssetTypes} />
          </div>

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