"use client";

import { useEffect, useMemo, useRef } from "react";

import { zodResolver } from "@hookform/resolvers/zod";
import { Star } from "lucide-react";
import { Controller, useForm } from "react-hook-form";

import { useDashboardFormSubmit } from "@/app/dashboard/_components/use-dashboard-form-submit";

import {
  FormPageHeader,
  FormPanel,
  FormSaveBar,
  FormSelect,
} from "@/app/dashboard/_components/form";
import { FormField } from "@/components/form/form-field";
import { Input } from "@/components/ui/input";

import {
  MODULE_LABEL_BY_VALUE,
  PARENT_TO_SALE,
  type MacroFormUsage,
} from "../constants";
import { ActiveReviewBadge } from "@/components/shared/status-pill";
import type { MacroAssetClassRow } from "../schema";
import { MACRO_ASSET_STATUS_FORM_OPTIONS } from "./constants";
import { ModuleMultiSelect } from "./module-multi-select";
import {
  macroAssetClassFormDefaults,
  macroAssetClassFormSchema,
  selectionHasNonStructureModules,
  selectionHasStructureModules,
  type MacroAssetClassFormValues,
} from "./schema";
import { TypeOptionMultiSelect } from "./type-option-multi-select";

const LIST_HREF = "/dashboard/master/macro-asset-class";
const CREATE_SUBMIT_HREF = "/dashboard/master/macro-asset-class/create/submit";
const UPDATE_SUBMIT_HREF = "/dashboard/master/macro-asset-class/update";

const SALE_CODES = new Set(Object.values(PARENT_TO_SALE));

export type MacroFormTypeOptions = {
  assetTypes: Array<{ id?: number; name: string; parentName: string }>;
  productTypes: string[];
};

type Props = {
  mode: "create" | "update";
  initial?: MacroAssetClassRow;
  formUsage?: MacroFormUsage;
  typeOptions?: MacroFormTypeOptions;
};

function withParentSales(codes: string[]): string[] {
  const next = [...codes];
  for (const code of codes) {
    const sale = PARENT_TO_SALE[code];
    if (sale && !next.includes(sale)) next.push(sale);
  }
  return [...new Set(next)];
}

function rowToFormValues(row: MacroAssetClassRow): MacroAssetClassFormValues {
  return {
    master_name: row.masterName,
    master_generated: withParentSales(row.masterGenerated),
    asset_types: row.assetTypes ?? [],
    product_types: row.productTypes ?? [],
    status: row.status,
  };
}

function availableTypeValues(
  allNames: string[],
  takenBy: Record<string, string[]>,
  currentlySelected: string[],
): string[] {
  return allNames.filter(
    (name) => currentlySelected.includes(name) || !(takenBy[name]?.length),
  );
}

function MacroAssetClassPreview({ values }: { values: MacroAssetClassFormValues }) {
  const visibleCodes = values.master_generated.filter((code) => !SALE_CODES.has(code));
  const moduleLabels = visibleCodes
    .map((code) => MODULE_LABEL_BY_VALUE[code] ?? code)
    .join(", ");
  const assetTypeLabel = values.asset_types.join(", ");
  const productTypeLabel = values.product_types.join(", ");

  return (
    <div className="overflow-hidden rounded-lg border bg-card shadow-sm">
      <div className="flex items-center justify-between gap-2 border-b bg-linear-to-br from-violet-500/10 via-primary/5 to-card px-3 py-2">
        <Star className="size-4 text-primary" />
        <ActiveReviewBadge
          status={values.status}
          label={
            values.status === "A"
              ? "Active"
              : values.status === "I"
                ? "Inactive"
                : "Under review"
          }
        />
      </div>
      <div className="space-y-2 p-3">
        <div className="font-semibold leading-tight">
          {values.master_name?.trim() || "Macro asset class name"}
        </div>
        <p className="text-muted-foreground text-xs leading-snug">
          {moduleLabels || "No modules selected"}
        </p>
        {assetTypeLabel ? (
          <p className="line-clamp-3 text-muted-foreground text-[11px] leading-snug">
            Asset types: {assetTypeLabel}
          </p>
        ) : null}
        {productTypeLabel ? (
          <p className="line-clamp-2 text-muted-foreground text-[11px] leading-snug">
            Product types: {productTypeLabel}
          </p>
        ) : null}
        <p className="text-muted-foreground text-[11px]">
          {visibleCodes.length} module
          {visibleCodes.length === 1 ? "" : "s"}
          {values.asset_types.length || values.product_types.length ? " · refined" : ""}
        </p>
      </div>
    </div>
  );
}

const EMPTY_USAGE: MacroFormUsage = {
  moduleFullClaims: {},
  modulePartialClaims: {},
  assetTypeUsage: {},
  productTypeUsage: {},
};

export function MacroAssetClassForm({
  mode,
  initial,
  formUsage = EMPTY_USAGE,
  typeOptions = { assetTypes: [], productTypes: [] },
}: Props) {
  const isUpdate = mode === "update";
  const seededRef = useRef(false);
  const prevShowAssetTypes = useRef(false);
  const prevShowProductTypes = useRef(false);

  const form = useForm<MacroAssetClassFormValues>({
    resolver: zodResolver(macroAssetClassFormSchema),
    defaultValues: initial ? rowToFormValues(initial) : macroAssetClassFormDefaults,
  });

  const watchValues = form.watch();
  const selectedModules = watchValues.master_generated ?? [];
  const showAssetTypes = selectionHasNonStructureModules(selectedModules);
  const showProductTypes = selectionHasStructureModules(selectedModules);

  const assetTypeOptions = useMemo(
    () =>
      typeOptions.assetTypes.map((item, index) => ({
        key: item.id != null ? `at-${item.id}` : `at-${item.parentName}-${item.name}-${index}`,
        value: item.name,
        label: item.name,
        hint: item.parentName || undefined,
        group: item.parentName || undefined,
      })),
    [typeOptions.assetTypes],
  );

  const productTypeOptions = useMemo(
    () =>
      typeOptions.productTypes.map((name, index) => ({
        key: `pt-${name}-${index}`,
        value: name,
        label: name,
      })),
    [typeOptions.productTypes],
  );

  const allAssetNames = useMemo(
    () => assetTypeOptions.map((item) => item.value),
    [assetTypeOptions],
  );
  const allProductNames = useMemo(
    () => productTypeOptions.map((item) => item.value),
    [productTypeOptions],
  );

  useEffect(() => {
    if (initial) {
      form.reset(rowToFormValues(initial));
      seededRef.current = true;
      prevShowAssetTypes.current = selectionHasNonStructureModules(
        withParentSales(initial.masterGenerated),
      );
      prevShowProductTypes.current = selectionHasStructureModules(
        withParentSales(initial.masterGenerated),
      );
    } else {
      seededRef.current = true;
    }
  }, [initial, form]);

  // Rising-edge auto-select: when modules first unlock a type picker, select all available.
  // Does not re-fill after the user clicks None.
  useEffect(() => {
    if (!seededRef.current) return;

    if (!showAssetTypes) {
      if ((watchValues.asset_types?.length ?? 0) > 0) {
        form.setValue("asset_types", []);
      }
    } else if (!prevShowAssetTypes.current && allAssetNames.length > 0) {
      form.setValue(
        "asset_types",
        availableTypeValues(allAssetNames, formUsage.assetTypeUsage, []),
      );
    }
    prevShowAssetTypes.current = showAssetTypes;

    if (!showProductTypes) {
      if ((watchValues.product_types?.length ?? 0) > 0) {
        form.setValue("product_types", []);
      }
    } else if (!prevShowProductTypes.current && allProductNames.length > 0) {
      form.setValue(
        "product_types",
        availableTypeValues(allProductNames, formUsage.productTypeUsage, []),
      );
    }
    prevShowProductTypes.current = showProductTypes;
  }, [
    showAssetTypes,
    showProductTypes,
    allAssetNames,
    allProductNames,
    formUsage.assetTypeUsage,
    formUsage.productTypeUsage,
    watchValues.asset_types,
    watchValues.product_types,
    form,
  ]);

  const { isSaving, submit } = useDashboardFormSubmit<MacroAssetClassFormValues>({
    mode: isUpdate ? "update" : "create",
    id: initial?.id,
    createUrl: CREATE_SUBMIT_HREF,
    updateUrl: UPDATE_SUBMIT_HREF,
    listHref: LIST_HREF,
    saveFailMessage: "Macro asset class could not be saved.",
    messages: {
      createFail: "Macro asset class could not be created.",
      updateFail: "Macro asset class could not be updated.",
      createSuccess: "Macro asset class created",
      updateSuccess: "Macro asset class updated",
    },
  });

  const onSubmit = form.handleSubmit(submit);

  const visibleModuleCount = (watchValues.master_generated ?? []).filter(
    (code) => !SALE_CODES.has(code),
  ).length;
  const typeRefineCount =
    (watchValues.asset_types?.length ?? 0) + (watchValues.product_types?.length ?? 0);

  return (
    <form
      onSubmit={onSubmit}
      className="flex min-h-0 flex-1 flex-col px-4 pt-4 md:px-6"
      data-content-padding="false"
    >
      <div className="min-w-0 flex-1">
      <FormPageHeader
        compact
        backHref={LIST_HREF}
        breadcrumb={[
          { label: "Master" },
          { label: "Macro asset class", href: LIST_HREF },
          { label: isUpdate ? "Update" : "Create new" },
        ]}
        titleIcon={<Star className="size-4 text-primary" />}
        title={
          isUpdate
            ? `Update ${initial?.masterName ?? "macro asset class"}`
            : "Create macro asset class"
        }
        description="Link modules and optionally refine by asset / product type."
      />

      <div className="grid gap-4 lg:grid-cols-[1fr_240px]">
        <div className="space-y-3">
          <FormPanel compact title="Details">
            <div className="grid gap-3 sm:grid-cols-2">
              <Controller
                name="master_name"
                control={form.control}
                render={({ field, fieldState }) => (
                  <FormField
                    label="Macro asset class name"
                    htmlFor="master_name"
                    required
                    error={fieldState.error}
                    className="sm:col-span-2"
                  >
                    <Input id="master_name" placeholder="e.g. Equities" {...field} />
                  </FormField>
                )}
              />

              <Controller
                name="status"
                control={form.control}
                render={({ field, fieldState }) => (
                  <FormField
                    label="Status"
                    htmlFor="status"
                    required
                    error={fieldState.error}
                  >
                    <FormSelect
                      id="status"
                      value={field.value}
                      onChange={field.onChange}
                      placeholder="Select status"
                      options={MACRO_ASSET_STATUS_FORM_OPTIONS}
                    />
                  </FormField>
                )}
              />
            </div>
          </FormPanel>

          <FormPanel
            compact
            title="Linked modules"
            description="Fully claimed modules are blocked; type-split modules stay available."
          >
            <Controller
              name="master_generated"
              control={form.control}
              render={({ field, fieldState }) => (
                <FormField
                  label="Modules"
                  htmlFor="master_generated"
                  required
                  error={fieldState.error}
                >
                  <ModuleMultiSelect
                    id="master_generated"
                    value={field.value}
                    onChange={field.onChange}
                    moduleFullClaims={formUsage.moduleFullClaims}
                    modulePartialClaims={formUsage.modulePartialClaims}
                  />
                </FormField>
              )}
            />
          </FormPanel>

          {(showAssetTypes || showProductTypes) ? (
            <div
              className={
                showAssetTypes && showProductTypes
                  ? "grid gap-3 lg:grid-cols-2"
                  : "grid gap-3"
              }
            >
              {showAssetTypes ? (
                <FormPanel
                  compact
                  title="Asset types"
                  description="Remaining types can be used on other macros."
                >
                  <Controller
                    name="asset_types"
                    control={form.control}
                    render={({ field, fieldState }) => (
                      <div className="space-y-1">
                        <TypeOptionMultiSelect
                          id="asset_types"
                          value={field.value}
                          onChange={field.onChange}
                          options={assetTypeOptions}
                          takenBy={formUsage.assetTypeUsage}
                          columns={showProductTypes ? 1 : 2}
                          emptyLabel="No category-17 asset types found for this tenant."
                        />
                        {fieldState.error?.message ? (
                          <p className="text-destructive text-xs">{fieldState.error.message}</p>
                        ) : null}
                      </div>
                    )}
                  />
                </FormPanel>
              ) : null}

              {showProductTypes ? (
                <FormPanel
                  compact
                  title="Structure product types"
                  description="For Structure / Structure Options modules."
                >
                  <Controller
                    name="product_types"
                    control={form.control}
                    render={({ field, fieldState }) => (
                      <div className="space-y-1">
                        <TypeOptionMultiSelect
                          id="product_types"
                          value={field.value}
                          onChange={field.onChange}
                          options={productTypeOptions}
                          takenBy={formUsage.productTypeUsage}
                          columns={showAssetTypes ? 1 : 2}
                          emptyLabel="No structure product types available."
                        />
                        {fieldState.error?.message ? (
                          <p className="text-destructive text-xs">{fieldState.error.message}</p>
                        ) : null}
                      </div>
                    )}
                  />
                </FormPanel>
              ) : null}
            </div>
          ) : null}
        </div>

        <aside className="lg:sticky lg:top-3 lg:self-start">
          <MacroAssetClassPreview values={watchValues} />
        </aside>
      </div>
      </div>

      <FormSaveBar
        className="mt-3"
        cancelHref={LIST_HREF}
        isSaving={isSaving}
        saveLabel="Save changes"
        status={
          <span>
            {visibleModuleCount} module{visibleModuleCount === 1 ? "" : "s"}
            {typeRefineCount > 0 ? ` · ${typeRefineCount} type refine` : ""}
          </span>
        }
        onReset={() =>
          form.reset(initial ? rowToFormValues(initial) : macroAssetClassFormDefaults)
        }
      />
    </form>
  );
}
