"use client";

import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { FC, useEffect, useId } from "react";
import { useFormContext } from "react-hook-form";
import Select, { MenuPosition } from "react-select";
import "./style.css";

type Props = {
  defaultItems?: any;
  name: string;
  idName: string;
  getLabel: (x: any) => void;
  isMulti?: boolean;
  onChange?: (x: any) => void;
  setOriginalValue?: (x: any) => void;
  isEnabled?: boolean;
  depend_on?: string | number | undefined;
  value?: "value" | "label";
  isClearable?: boolean;
  placeholder?: string | undefined;
  height?: number;
  filter?: string | undefined;
  initialData?: any;
  menuPosition?: MenuPosition | undefined;
  isDisabled?: boolean;
};

const DropdownList: FC<Props> = ({
  defaultItems,
  name,
  idName,
  getLabel,
  isMulti = true,
  onChange = () => { },
  setOriginalValue = () => { },
  isEnabled = true,
  depend_on = undefined,
  value = "value",
  isClearable = true,
  placeholder = undefined,
  height = 42,
  filter = undefined,
  initialData = undefined,
  menuPosition = "fixed",
  isDisabled = false,
}) => {
  const {
    setValue,
    watch,
    formState: { errors },
    clearErrors,
  } = useFormContext();
  const id = useId();
  const getDropdownList = async () => {
    let url = `/api/dropdown?item=${name}s`;
    if (depend_on) {
      url = `${url}&id=${depend_on}`;
    }
    if (filter) {
      url = `${url}&filter=${filter}`;
    }
    const { data } = await axios.get(url);
    return data?.data;
  };
  const {
    data: dropdownList,
    isLoading,
    refetch,
  } = useQuery({
    queryKey: [`${name}-${id}-dropdown`],
    queryFn: () => getDropdownList(),
    retry: 0,
    enabled: isEnabled,
    initialData: initialData,
  });
  useEffect(() => {
    if (depend_on) {
      refetch();
    }
  }, [depend_on]);
  // Watch for form value changes (including async loaded values)
  const watchedValue = watch(name);
  const watchedIdValue = watch(idName);

  // useEffect(() => {
  //   console.log(`Form value changed for ${name}:`, watchedValue, `ID value:`, watchedIdValue);
  // }, [watchedValue, watchedIdValue, name, idName])

  const handleChange = (selectedOption: any) => {
    if (!isMulti) {
      setValue(idName, selectedOption?.value);
      onChange(selectedOption);
      const original = dropdownList?.filter(
        (item: any) => item?.id === selectedOption?.value
      );

      if (original?.length > 0) {
        setOriginalValue(original[0]);
      }
    }
    if (isMulti) {
      const option = selectedOption?.map((item: any) => Object.values(item)[0]);
      setValue(idName, option);
      onChange(option);
    }
    clearErrors(idName);
  };

  const getSelectedValue = () => {
    // First priority: check if there's a watched ID value from the form
    if (watchedIdValue && dropdownList) {
      if (!isMulti) {
        // For single select, find the item by ID in dropdownList
        const selectedItem = dropdownList.find((item: any) => item.id === watchedIdValue);
        if (selectedItem) {
          return {
            value: selectedItem.id,
            label: getLabel(selectedItem)
          };
        }
      } else {
        // For multi select
        if (Array.isArray(watchedIdValue)) {
          return watchedIdValue.map((id: any) => {
            const item = dropdownList.find((item: any) => item.id === id);
            return item ? {
              value: item.id,
              label: getLabel(item),
            } : null;
          }).filter(Boolean);
        }
      }
    }

    // Second priority: check if there's a watched value object from the form
    if (watchedValue && dropdownList) {
      if (!isMulti) {
        // For single select, watchedValue should be the zone object
        if (watchedValue?.id) {
          return {
            value: watchedValue.id,
            label: getLabel(watchedValue)
          };
        }
      } else {
        // For multi select
        return Array.isArray(watchedValue)
          ? watchedValue.map((item: any) => ({
            value: item?.id,
            label: getLabel(item),
          }))
          : [];
      }
    }

    // Third priority: defaultItems prop
    if (defaultItems) {
      if (!isMulti) {
        if (typeof defaultItems === "string") {
          return { value: defaultItems, label: defaultItems };
        }
        if (defaultItems?.id) {
          return { value: defaultItems?.id, label: getLabel(defaultItems) };
        }
      } else {
        return Array.isArray(defaultItems)
          ? defaultItems.map((item: any) => ({
            value: item?.id,
            label: getLabel(item),
          }))
          : [];
      }
    }

    // Default fallback
    if (!isMulti) {
      return null; // Let react-select handle the placeholder
    }
    return [];
  };
  useEffect(() => {
    if (defaultItems?.id) {
      setValue(idName, defaultItems?.id);
    }
    if (Array.isArray(defaultItems)) {
      const items = defaultItems?.map((item: any) => item?.id);
      setValue(idName, items);
    }
  }, [defaultItems]);

  const options = dropdownList?.map((item: any) => ({
    value: item?.id,
    label: getLabel(item),
  }));

  const customStyles = {
    control: (base: any) => ({
      ...base,
      minHeight: height,
      background: "rgb(249 250 251)",
      borderRadius: "5px",
    }),
  };
  return (
    <>
      <Select
        instanceId={id}
        id={`${id}`}
        className="w-full dark:bg-gray-800"
        onChange={handleChange}
        value={getSelectedValue()}
        placeholder={placeholder || `Select ${name}`}
        options={options}
        isMulti={isMulti}
        isClearable={isClearable}
        isLoading={isLoading}
        isSearchable
        classNamePrefix="react-select"
        styles={customStyles}
        menuPosition={menuPosition}
        isDisabled={isDisabled}
      />
      {errors?.[idName] && (
        <span className="text-red-500">{name} is required</span>
      )}
    </>
  );
};

export default DropdownList;
