"use client";

import * as React from "react";

import { Plus } from "lucide-react";
import {
  useFormContext,
  useWatch,
  type Control,
  type FieldPath,
  type FieldValues,
} from "react-hook-form";
import { toast } from "sonner";

import { createAssetTypeClient } from "@/app/customer/_lib/create-asset-type-client";
import { knownAssetTypeLabel } from "@/app/customer/_lib/known-yii-master-labels";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";

import { SelectField, type SelectOption } from "./select-field";

type CreatedOption = { value: string; label: string };

function normalizeSelectOption(option: SelectOption): CreatedOption {
  if (typeof option === "string") {
    return { value: option, label: option };
  }
  return { value: String(option.value), label: option.label };
}

function mergeSelectOptions(
  options: readonly SelectOption[],
  extras: CreatedOption[],
): CreatedOption[] {
  const byValue = new Map<string, CreatedOption>();
  for (const option of options) {
    const normalized = normalizeSelectOption(option);
    if (!normalized.value) continue;
    byValue.set(normalized.value, normalized);
  }
  for (const extra of extras) {
    if (!extra.value) continue;
    byValue.set(extra.value, extra);
  }
  return [...byValue.values()];
}

function QuickAddAssetTypeButton({
  assetClassId,
  onCreated,
}: {
  assetClassId: () => string;
  onCreated: (option: CreatedOption) => void;
}) {
  const [open, setOpen] = React.useState(false);
  const [code, setCode] = React.useState("");
  const [title, setTitle] = React.useState("");
  const [error, setError] = React.useState<string | null>(null);
  const [saving, setSaving] = React.useState(false);

  function resetForm() {
    setCode("");
    setTitle("");
    setError(null);
  }

  async function handleSave() {
    const trimmedTitle = title.trim();
    if (!trimmedTitle) {
      setError("Title is required.");
      return;
    }

    const parentMaster = assetClassId();
    if (!parentMaster) {
      window.alert("Please Select Asset Class");
      return;
    }

    setSaving(true);
    setError(null);

    try {
      const created = await createAssetTypeClient({
        name: trimmedTitle,
        code: code.trim() || undefined,
        parentMaster,
      });
      onCreated(created);
      toast.success("Asset type created");
      resetForm();
      setOpen(false);
    } catch (caught) {
      setError(
        caught instanceof Error ? caught.message : "Asset type could not be created.",
      );
    } finally {
      setSaving(false);
    }
  }

  return (
    <Popover
      open={open}
      onOpenChange={(next) => {
        const parentMaster = assetClassId();
        if (next && !parentMaster) {
          window.alert("Please Select Asset Class");
          return;
        }
        setOpen(next);
        if (!next) resetForm();
      }}
    >
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          size="icon-xs"
          className="text-primary"
          aria-label="Add asset type"
          title="Add asset type"
        >
          <Plus className="size-3.5" />
        </Button>
      </PopoverTrigger>
      <PopoverContent align="end" className="w-80">
        <div className="flex gap-2">
          <Input
            value={code}
            onChange={(event) => setCode(event.target.value)}
            placeholder="Code"
            maxLength={6}
            disabled={saving}
            className="w-[4.5rem] shrink-0"
            onKeyDown={(event) => {
              if (event.key === "Enter") {
                event.preventDefault();
                void handleSave();
              }
            }}
          />
          <Input
            value={title}
            onChange={(event) => setTitle(event.target.value)}
            placeholder="Enter Your title"
            disabled={saving}
            onKeyDown={(event) => {
              if (event.key === "Enter") {
                event.preventDefault();
                void handleSave();
              }
            }}
          />
          <Button type="button" size="sm" disabled={saving} onClick={() => void handleSave()}>
            {saving ? "Saving…" : "Save"}
          </Button>
        </div>
        {error ? <p className="text-destructive text-xs">{error}</p> : null}
      </PopoverContent>
    </Popover>
  );
}

type AssetTypeSelectFieldProps<T extends FieldValues> = {
  control: Control<T>;
  name?: FieldPath<T>;
  assetClassName?: FieldPath<T>;
  label?: string;
  options: readonly SelectOption[];
  disabled?: boolean;
  className?: string;
  searchPlaceholder?: string;
};

export function AssetTypeSelectField<T extends FieldValues>({
  control,
  name = "a_type" as FieldPath<T>,
  assetClassName = "a_class" as FieldPath<T>,
  label = "Asset Type",
  options,
  disabled,
  className,
  searchPlaceholder = "Search asset type…",
}: AssetTypeSelectFieldProps<T>) {
  const { getValues, setValue } = useFormContext<T>();
  const selectedValue = String(useWatch({ control, name }) ?? "").trim();
  const [extraOptions, setExtraOptions] = React.useState<CreatedOption[]>([]);

  const mergedOptions = React.useMemo(() => {
    const merged = mergeSelectOptions(options, extraOptions);
    if (
      selectedValue &&
      !merged.some((option) => option.value === selectedValue)
    ) {
      const values = getValues() as Record<string, unknown>;
      const titleFromModel = String(values.asset_type_title ?? "").trim();
      merged.push({
        value: selectedValue,
        label: titleFromModel || knownAssetTypeLabel(selectedValue) || selectedValue,
      });
    }
    return merged;
  }, [extraOptions, getValues, options, selectedValue]);

  React.useEffect(() => {
    if (!selectedValue) return;
    const byLabel = mergedOptions.find(
      (option) => option.value !== selectedValue && option.label === selectedValue,
    );
    if (!byLabel) return;
    setValue(name, byLabel.value as T[typeof name], {
      shouldDirty: false,
      shouldValidate: false,
    });
  }, [mergedOptions, name, selectedValue, setValue]);

  return (
    <SelectField
      control={control}
      name={name}
      label={label}
      options={mergedOptions}
      searchable
      searchPlaceholder={searchPlaceholder}
      disabled={disabled}
      className={className}
      labelAction={
        <QuickAddAssetTypeButton
          assetClassId={() => String(getValues(assetClassName) ?? "").trim()}
          onCreated={(option) => {
            setExtraOptions((current) =>
              current.some((item) => item.value === option.value)
                ? current
                : [...current, option],
            );
            setValue(name, option.value as T[typeof name], {
              shouldDirty: true,
              shouldValidate: true,
              shouldTouch: true,
            });
          }}
        />
      }
    />
  );
}
