import React, { JSX, useRef, useState } from "react";
import { Trash2, X, ChevronDown, Search } from "lucide-react";
import { useTranslation } from "react-i18next";
import {
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "../../ui/form";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "../../ui/select";
import { MultiSelect } from "../../ui/multi-select";
import { Input } from "../../ui/input";
import { Button } from "../../ui/button";
import TreeView, { TreeViewItem } from "@/shared/common/ui/treeSelect";

import { Controller } from "react-hook-form";
import { SingleSelect } from "../../ui/single-select";
import { useLocalizedName } from "../../localizedName";
import i18next from "i18next";
import { getCheckedLeafNodes } from "@/record-management/components/userRecords/common/treeUtils";

type BaseSelectOption = {
  label: string;
  value: string;
  unitId?: string;
};
interface CustomSelectProps {
  form: any; // your react-hook-form instance
  name: string;
  label: string;
  placeholder: string;
  options: { id: string; name: { en: string; am: string } }[];
  localizedName: (name: { en: string; am: string }) => string;
}

// 1️⃣ Form Select Field
export const FormSelectField = ({
  control,
  name,
  label,
  options,
  placeholder,
  className,
  customLabel,
  disabled,
  onCustomChange,
}: {
  control: any;
  name: string;
  label: string;
  options: BaseSelectOption[];
  placeholder?: string;
  className?: string;
  customLabel?: React.ReactNode;
  disabled?: boolean;
  onCustomChange?: (value: string) => void;
}) => (
  <FormField
    control={control}
    name={name}
    render={({ field }) => (
      <FormItem className={className || "space-y-1"}>
        {customLabel ? (
          customLabel
        ) : (
          <FormLabel>
            {name === "headerId" ||
            name === "footerId" ||
            name === "recordType" ||
            name === "initiationType" ||
            name === "initiatedAs" ? (
              <span>
                {label} <span className="text-red-500 text-xl">*</span>
              </span>
            ) : (
              label
            )}
          </FormLabel>
        )}
        <FormControl>
          <Select
            value={field.value ?? ""}
            disabled={disabled}
            onValueChange={(value) => {
              field.onChange(value);
              onCustomChange?.(value);
            }}
          >
            <SelectTrigger className="w-full">
              <SelectValue placeholder={placeholder} />
            </SelectTrigger>
            <SelectContent className="w-full max-w-full sm:max-w-md z-[60] overflow-x-auto">
              {options.map((option) => (
                <SelectItem key={option.value} value={option.value}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </FormControl>
        <FormMessage />
      </FormItem>
    )}
  />
);

export const FormSingleSelectField = ({
  control,
  name,
  label,
  options,
  placeholder = "Select option",
  onCustomChange,
}: {
  control: any;
  name: string;
  label: string;
  options: BaseSelectOption[];
  placeholder?: string;
  onCustomChange?: (selectedValue: string) => void;
}) => (
  <FormField
    control={control}
    name={name}
    render={({ field }) => {
      const handleChange = (value: string) => {
        field.onChange(value);
        if (onCustomChange) onCustomChange(value);
      };

      return (
        <FormItem className="space-y-1">
          <FormLabel>{label}</FormLabel>
          <FormControl>
            <SingleSelect
              options={options}
              value={field.value || ""}
              onValueChange={handleChange}
              placeholder={placeholder}
            />
          </FormControl>
          <FormMessage />
        </FormItem>
      );
    }}
  />
);
// 2️⃣ Multi Select Field
export const FormMultiSelectField = ({
  control,
  name,
  label,
  options,
  placeholder = "Select options",
  maxCount,
  disabled,
  onCustomChange,
}: {
  control: any;
  name: string;
  label: string;
  options: BaseSelectOption[];
  placeholder?: string;
  maxCount?: number;
  disabled?: boolean;
  onCustomChange?: (selectedValues: string[]) => void;
}) => (
  <FormField
    control={control}
    name={name}
    render={({ field }) => {
      const handleChange = (values: string[]) => {
        field.onChange(values);
        if (onCustomChange) onCustomChange(values);
      };

      const fieldValue = Array.isArray(field.value)
        ? field.value
        : field.value
          ? [field.value]
          : [];

      return (
        <FormItem className="space-y-1">
          <FormLabel>
            {name === "toPositions" ||
             name === "toEmployees" ||
             name === "collaborators" ||
             name === "receivingDepartments" ||
             name === "assignedEmployees" ? (
              <span>
                {label} <span className="text-red-500 text-xl">*</span>
              </span>
            ) : (
              label
            )}
          </FormLabel>
          <FormControl>
            <MultiSelect
              options={options}
              value={fieldValue} // controlled value
              onValueChange={handleChange} // controlled onChange
              placeholder={placeholder}
              maxCount={maxCount || 5}
              disabled={disabled}
              className="w-full max-w-full sm:max-w-md overflow-x-auto"
              animation={0}
            />
          </FormControl>
          <FormMessage />
        </FormItem>
      );
    }}
  />
);

export const FormTreeSelectField = ({
  control,
  name,
  label,
  options,
  handleCheckChange,
  collapsible = false,
  localizedName,
  selectedCountResolver,
}: {
  control: any;
  name: string;
  label: string;
  options: TreeViewItem[];
  handleCheckChange?:
    | ((item: TreeViewItem | TreeViewItem[], checked: boolean) => void)
    | undefined;
  collapsible?: boolean;
  localizedName: (
    name?:
      | {
          am: string;
          en: string;
        }
      | undefined,
  ) => string;
  selectedCountResolver?: (value: unknown) => number;
}) => {
  const { t } = useTranslation();
  const [isOpen, setIsOpen] = React.useState(!collapsible);
  const containerRef = React.useRef<HTMLDivElement>(null);

  // Close dropdown on outside click
  React.useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (
        containerRef.current &&
        !containerRef.current.contains(event.target as Node)
      ) {
        setIsOpen(false);
      }
    }
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, []);

  if (collapsible) {
    return (
      <FormField
        control={control}
        name={name}
        rules={{ required: `${label} is required` }}
        render={({ field }) => {
          const selectedCount = selectedCountResolver
            ? selectedCountResolver(field.value)
            : getCheckedLeafNodes(Array.isArray(field.value) ? field.value : [])
                .length;

          return (
            <FormItem
              ref={containerRef}
              className="sm:col-span-3 w-full min-w-0 max-w-full"
            >
              <FormLabel>
                {name === "receivingUnitIds" ? (
                  <span>
                    {label} <span className="text-red-500 text-xl">*</span>
                  </span>
                ) : (
                  label
                )}
              </FormLabel>
              <div className="relative w-full min-w-0 max-w-full">
                <Button
                  type="button"
                  variant="outline"
                  onClick={() => setIsOpen(!isOpen)}
                  className="h-auto min-h-10 w-full max-w-full justify-between gap-2 py-2"
                >
                  <span className="block min-w-0 flex-1 truncate text-left">
                    {selectedCount > 0
                      ? `${selectedCount} unit(s) selected`
                      : `${t("common.select")} ${label}`}
                  </span>
                  <ChevronDown
                    className={`h-4 w-4 shrink-0 transition-transform ${
                      isOpen ? "rotate-180" : ""
                    }`}
                  />
                </Button>

                {isOpen && (
                  <div className="absolute left-0 right-0 z-50 mt-1 w-full min-w-0 max-w-full overflow-hidden rounded-md border bg-background p-2 shadow-md">
                    <TreeView
                      embedded
                      className="max-h-[55vh] overflow-y-auto sm:max-h-[450px]"
                      data={options}
                      showExpandAll={false}
                      showCheckboxes
                      onCheckChange={handleCheckChange}
                      localizedName={localizedName}
                    />
                  </div>
                )}
              </div>
              <FormMessage />
            </FormItem>
          );
        }}
      />
    );
  }

  return (
    <FormField
      control={control}
      name={name}
      rules={{ required: `${label} is required` }}
      render={() => (
        <FormItem className="sm:col-span-3 w-full min-w-0">
          <FormLabel>{label}</FormLabel>
          <TreeView
            className="max-h-[55vh] overflow-y-auto sm:max-h-[450px]"
            data={options}
            showExpandAll={false}
            showCheckboxes
            onCheckChange={handleCheckChange}
            localizedName={localizedName}
          />
          <FormMessage />
        </FormItem>
      )}
    />
  );
};

// 3️⃣ Addable List Field (string-based)
export const FormAddableList = ({
  form,
  name,
  label,
  placeholder = "",
  valueAdapter,
}: {
  form: any;
  name: string;
  label: string;
  placeholder?: string;
  valueAdapter?: {
    getDisplayItems: (fieldValue: unknown) => string[];
    onItemsChange: (items: string[], fieldValue: unknown) => unknown;
  };
}) => {
  const { t } = useTranslation();
  const [pendingValue, setPendingValue] = useState("");

  return (
    <FormField
      control={form.control}
      name={name}
      render={({ field }) => {
        const items = valueAdapter
          ? valueAdapter.getDisplayItems(field.value)
          : Array.isArray(field.value)
            ? field.value
            : [];

        const handleAdd = () => {
          const value = pendingValue.trim();
          if (value && !items.includes(value)) {
            const updatedItems = [...items, value];
            field.onChange(
              valueAdapter
                ? valueAdapter.onItemsChange(updatedItems, field.value)
                : updatedItems,
            );
            setPendingValue("");
          }
        };

        const handleDelete = (index: number) => {
          const updatedItems = items.filter(
            (_: string, i: number) => i !== index,
          );
          field.onChange(
            valueAdapter
              ? valueAdapter.onItemsChange(updatedItems, field.value)
              : updatedItems,
          );
        };

        const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
          if (e.key === "Enter") {
            e.preventDefault();
            handleAdd();
          }
        };

        return (
          <FormItem className="space-y-2">
            <FormLabel>{label}</FormLabel>
            <div className="flex flex-col sm:flex-row gap-2">
              <FormControl className="flex-1">
                <Input
                  placeholder={placeholder}
                  value={pendingValue}
                  onChange={(e) => setPendingValue(e.target.value)}
                  onKeyDown={handleKeyDown}
                  onBlur={handleAdd}
                />
              </FormControl>
              <Button
                type="button"
                onClick={handleAdd}
                className="bg-primary-500 text-white hover:bg-primary-600"
              >
                {t("addRecord.Add")}
              </Button>
            </div>

            {items.length > 0 && (
              <div className="flex flex-wrap gap-1 mt-2">
                {items.map((unit: string, index: number) => (
                  <div
                    key={`${unit}-${index}`}
                    className="flex items-center gap-1 px-2 py-1 bg-primary-50 text-primary-700 border border-primary-100 rounded-md"
                  >
                    <span className="text-sm truncate max-w-[200px]">
                      {unit}
                    </span>
                    <X
                      size={14}
                      className="cursor-pointer text-primary-700 hover:text-red-600 ml-1"
                      onClick={() => handleDelete(index)}
                    />
                  </div>
                ))}
              </div>
            )}

            <FormMessage />
          </FormItem>
        );
      }}
    />
  );
};
export const ClearableSelect = ({
  form,
  name,
  label,
  placeholder = "",
  options,
  localizedName,
}: {
  form: any;
  name: string;
  label: string;
  placeholder?: string;
  options: { id: string; name: any }[];
  localizedName: (name: any) => string;
}) => {
  return (
    <FormItem className="space-y-2">
      <FormLabel>{label}</FormLabel>
      <FormField
        control={form.control}
        name={name}
        render={({ field }) => (
          <>
            {field.value ? (
              // Selected value with X to clear
              <div className="flex items-center justify-between border text-sm rounded-md px-3 py-2 bg-gray-50">
                <span>
                  {localizedName(
                    options.find((o) => o.id === field.value)?.name,
                  )}
                </span>
                <X
                  size={17}
                  className="cursor-pointer text-primary-700 hover:text-red-600 ml-1"
                  onClick={() => field.onChange("")}
                />
              </div>
            ) : (
              // Select dropdown
              <Select
                value={field.value}
                onValueChange={field.onChange}
                defaultValue={field.value}
              >
                <FormControl>
                  <SelectTrigger className="w-full">
                    <SelectValue placeholder={placeholder} />
                  </SelectTrigger>
                </FormControl>
                <SelectContent className="w-full max-w-full sm:max-w-md z-[60] overflow-x-auto">
                  {options?.map((item) => (
                    <SelectItem key={item.id} value={item.id}>
                      {localizedName(item.name)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
            <FormMessage />
          </>
        )}
      />
    </FormItem>
  );
};

export const CustomSelect = ({
  form,
  name,
  label,
  placeholder,
  options,
  localizedName,
}: CustomSelectProps) => {
  const { t } = useTranslation();
  return (
    <div className="flex flex-col gap-1">
      <label className="text-sm font-medium">{label}</label>
      <Controller
        control={form.control}
        name={name}
        render={({ field }) => {
          const matchingOption = options.find((opt) => {
            const english = opt.name?.en ?? "";
            const amharic = opt.name?.am ?? "";
            return (
              field.value === opt.id ||
              field.value === english ||
              field.value === amharic
            );
          });

          // Treat undefined, null, and empty string as no selection
          const hasValue = field.value !== undefined && field.value !== null && field.value !== "";
          const resolvedValue = matchingOption && hasValue
            ? matchingOption.id
            : "";

          return (
            <Select
              value={resolvedValue}
              onValueChange={(val) => {
                if (val === "__clear__" || val === "") {
                  field.onChange("");
                } else {
                  field.onChange(val);
                }
              }}
            >
              <SelectTrigger className="w-full">
                <SelectValue placeholder={placeholder} />
              </SelectTrigger>
              <SelectContent>
                {options.map((opt) => (
                  <SelectItem key={opt.id} value={opt.id}>
                    {localizedName(opt.name)}
                  </SelectItem>
                ))}
                <SelectItem value="__clear__">{t("common.Cancel")}</SelectItem>
              </SelectContent>
            </Select>
          );
        }}
      />
    </div>
  );
};

export interface TreeViewItemO {
  id: string;
  name: string | { en: string; am: string }; // allow localized or raw
  value?: string;
  children?: TreeViewItem[];
}

interface SimpleTreeSelectProps {
  label: string;
  options: TreeViewItemO[];
  value: string | null;
  onChange: (id: string | null) => void;
  collapsible?: boolean;
  localizedName?: (name?: { en?: string; am?: string } | undefined) => string;
  className?: string;
}

export const SimpleTreeSelect = ({
  label,
  options,
  value,
  onChange,
  collapsible = false,
  localizedName,
  className,
}: SimpleTreeSelectProps) => {
  const [isOpen, setIsOpen] = useState(!collapsible);
  const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());

  const toggleExpand = (id: string) => {
    const newSet = new Set(expandedItems);
    if (newSet.has(id)) newSet.delete(id);
    else newSet.add(id);
    setExpandedItems(newSet);
  };

  const handleSelect = (id: string) => {
    onChange(id);
    // Optional: close dropdown after selection
    // setIsOpen(false);
  };

  // Get full path for a selected item
  const findSelectedPath = (
    items: TreeViewItemO[],
    parentPath: string[] = [],
  ): string | null => {
    for (const item of items) {
      const name =
        typeof item.name === "string"
          ? item.name
          : (localizedName?.(item.name) ?? item.name.en);

      if (item.id === value) {
        return [...parentPath, name].join(" / ");
      }

      if (item.children && item.children.length > 0) {
        const childPath = findSelectedPath(item.children, [
          ...parentPath,
          name,
        ]);
        if (childPath) return childPath;
      }
    }
    return null;
  };

  const renderTree = (items: TreeViewItemO[]): JSX.Element[] => {
    return items.flatMap((item) => {
      const hasChildren = item.children && item.children.length > 0;
      const isExpanded = expandedItems.has(item.id);

      // Determine if any child is selected to highlight parent
      const isParentSelected = hasChildren
        ? item.children!.some((child) => child.id === value)
        : false;

      // Skip single-unit org
      if (hasChildren && item.children!.length === 1) {
        return renderTree(item.children!);
      }

      const itemLabel =
        typeof item.name === "string"
          ? item.name
          : (localizedName?.(item.name) ?? item.name.en);

      return (
        <div key={item.id} className="ml-4 mb-1">
          <div className="flex items-center space-x-2">
            {hasChildren && (
              <button
                type="button"
                onClick={() => toggleExpand(item.id)}
                className="w-4 h-4 flex items-center justify-center"
              >
                <ChevronDown
                  className={`h-3 w-3 transition-transform ${
                    isExpanded ? "rotate-180" : ""
                  }`}
                />
              </button>
            )}

            <label className="flex items-center space-x-2">
              <input
                type="radio"
                name="unit-select"
                checked={value === item.id || isParentSelected}
                onChange={() => handleSelect(item.id)}
              />
              <span className={isParentSelected ? "font-semibold" : ""}>
                {itemLabel}
              </span>
            </label>
          </div>

          {hasChildren && isExpanded && (
            <div className="ml-4">{renderTree(item.children!)}</div>
          )}
        </div>
      );
    });
  };

  const selectedPathLabel = findSelectedPath(options);

  return (
    <div className={className ?? "mb-4"}>
      <label className="block font-semibold mb-1">{label}</label>

      {collapsible && (
        <Button
          type="button"
          variant="outline"
          onClick={() => setIsOpen(!isOpen)}
          className="w-full max-w-lg justify-between mb-2"
        >
          <span className="truncate">
            {selectedPathLabel ?? label}
          </span>
          <ChevronDown
            className={`h-4 w-4 transition-transform ${
              isOpen ? "rotate-180" : ""
            }`}
          />
        </Button>
      )}

      {isOpen && (
        <div className="border rounded-md p-2 bg-background max-h-96 overflow-y-auto max-w-lg">
          {renderTree(options)}
        </div>
      )}
    </div>
  );
};

export const SelectedItemsChips = ({
  items,
  onRemove,
  label,
  localizedName,
}: {
  items: TreeViewItem[];
  onRemove: (value: string) => void;
  label?: string;
  localizedName: (
    name?:
      | {
          am: string;
          en: string;
        }
      | undefined,
  ) => string;
}) => {
  if (!items?.length) return null;

  return (
    <div className="grid gap-2 sm:col-span-3">
      {label && <p className="text-sm font-semibold mb-2">{label}</p>}
      <div className="flex flex-wrap gap-2">
        {items.map((item) => (
          <div
            key={item.id}
            className="flex items-center bg-primary-100 text-primary-800 px-3 py-1 rounded-full text-sm"
          >
            <span className="truncate max-w-[180px]">
              {localizedName(item.name)}
            </span>
            <button
              type="button"
              className="ml-2 text-red-500 hover:text-red-700"
              onClick={() => {
                onRemove(item.id);
              }}
            >
              ×
            </button>
          </div>
        ))}
      </div>
    </div>
  );
};
