import {
  DropdownButtonContainer,
  OptionContainer,
  DropdownInput,
  DropdownOptions,
} from "./SingleDropdown.styled";
import ChevronDown from "../../../assets/svgs/chevron-down.svg";
import X from "../../../assets/svgs/x.svg";
import { InputStyle } from "../../Input/Input.styled";
import { useEffect, useMemo, useRef, useState } from "react";
import { gray, primary } from "../../../core/colors/colors";
import { CommonDropdownTypes } from "../DropdownTypes";
import DropdownSearch from "../DropdownSearch";

export type DropdownStatus = "DEFAULT" | "FOCUS";

export type SingleDropdownProps<T> = CommonDropdownTypes<T> & {
  value?: T;
};

const SingleDropdown = <T extends {}>({
  value, // dropdown input value
  options, // dropdown options
  optionKey, // 고유하게 식별할 수 있는 값
  optionLabel, // 표출 될 문자
  onClick,
  enableClearButton = true, // x 버튼
  enableSearch = true, // dropdown option 검색 창
  optionElement, // 기본적인 dropdown에 더 추가하고 싶은것이 있을 때 ex> 샤프 2,000원
  disable = false,
  placeholder,
}: SingleDropdownProps<T>) => {
  // dropdown input focus
  const [isFocus, setIsFocus] = useState<boolean>(false);
  // 검색할 문자
  const [filterValue, setFilterValue] = useState<string>("");
  // 검색 된 options
  const [filteredOptions, setFilteredOptions] = useState<T[]>([...options]);
  const status: DropdownStatus = useMemo(() => {
    if (isFocus) return "FOCUS";
    return "DEFAULT";
  }, [isFocus]);
  const dropdownRef = useRef<HTMLDivElement>(null);

  const style: {
    [key in DropdownStatus]: { [style in "borderColor"]: string };
  } = {
    DEFAULT: {
      borderColor: gray[300],
    },
    FOCUS: {
      borderColor: primary[500],
    },
  };

  const renderDropdownOptions = () => {
    const valueToShow =
      filteredOptions?.length !== 0 ? filteredOptions : options;
    return (
      <OptionContainer className={optionElement && "jsx_element"}>
        {valueToShow.map((option, idx) => (
          <button
            key={`${idx}_${optionKey(option)}`}
            className={
              value && optionKey(option) === optionKey(value) ? "selected" : ""
            }
            onClick={() => {
              onClick(option);
              setIsFocus(false);
            }}
          >
            {optionElement ? (
              optionElement({ option })
            ) : (
              <p>{optionLabel(option)}</p>
            )}
          </button>
        ))}
      </OptionContainer>
    );
  };

  // 바깥을 클릭했을 때 focus들 false
  useEffect(() => {
    const outsideClick = (e: MouseEvent) => {
      if (
        dropdownRef.current &&
        !dropdownRef.current.contains(e.target as Node)
      ) {
        setIsFocus(false);
        setFilterValue("");
      }
    };
    window.addEventListener("mousedown", outsideClick);
    return () => window.removeEventListener("mousedown", outsideClick);
  }, [dropdownRef]);

  return (
    <div ref={dropdownRef}>
      <DropdownInput>
        <InputStyle
          value={(value && optionLabel(value)) || ""}
          onClick={() => {
            setIsFocus(!isFocus);
            setFilteredOptions([...options]);
            setFilterValue("");
          }}
          style={{
            ...style[status],
            paddingRight: enableClearButton ? "64px" : "40px",
          }}
          placeholder={placeholder}
          disabled={disable}
          readOnly
        />
        <DropdownButtonContainer>
          {value && optionKey(value) && enableClearButton ? (
            <button
              onClick={() => {
                onClick(undefined);
                setIsFocus(false);
                setFilterValue("");
              }}
              disabled={disable}
            >
              <X />
            </button>
          ) : null}
          <button
            onClick={() => {
              setIsFocus(!isFocus);
              setFilterValue("");
            }}
            disabled={disable}
          >
            <ChevronDown
            // style={{
            //   stroke: isFocus ? gray[600] : "",
            //   transform: isFocus ? "rotate(180deg)" : "",
            // }}
            />
          </button>
        </DropdownButtonContainer>
      </DropdownInput>
      {isFocus && (
        <>
          {enableSearch && (
            <DropdownSearch<T>
              value={filterValue}
              options={options}
              optionLabel={(value) => optionLabel(value)}
              onChange={(e) => {
                !e.target.value && setFilteredOptions([...options]);
                setFilterValue(e.target.value);
              }}
              onSearch={(filteredOptions) =>
                setFilteredOptions(filteredOptions)
              }
              filterValueClear={() => {
                setFilterValue("");
                setFilteredOptions([...options]);
              }}
              placeholder="검색 후 Enter 키를 눌러주세요"
            />
          )}
          <DropdownOptions
            style={
              enableSearch
                ? {
                    maxHeight: "343px",
                    marginTop: 0,
                    paddingTop: 0,
                    borderTop: 0,
                    borderTopLeftRadius: 0,
                    borderTopRightRadius: 0,
                  }
                : {}
            }
          >
            {options.length === 0 ||
            (enableSearch && filteredOptions.length === 0) ? (
              <div className="empty">데이터가 없습니다</div>
            ) : (
              renderDropdownOptions()
            )}
          </DropdownOptions>
        </>
      )}
    </div>
  );
};

export default SingleDropdown;
