import { Checkbox, Flex, Select } from 'antd';
import type { SelectProps } from 'antd';
import { useEffect, useMemo, useState } from 'react';
import type { CheckComboUIProps, SelectOptionItem } from './types';

function normalizeKeyword(text: string) {
  return text.trim().toLowerCase();
}

export function CheckComboUI({
  data,
  value,
  defaultValue,
  onChange,
  showSearch = true,
  allowClear = true,
  placeholder = '항목을 선택하세요',
  ...restProps
}: CheckComboUIProps) {
  const [selectedCodes, setSelectedCodes] = useState<string[]>(() => value ?? defaultValue ?? []);

  useEffect(() => {
    if (value !== undefined) {
      setSelectedCodes(value);
    }
  }, [value]);

  const options = useMemo<SelectProps['options']>(
    () =>
      data.map((item) => ({
        value: item.code,
        label: item.value,
        item,
      })),
    [data],
  );

  const itemMap = useMemo(
    () =>
      new Map<string, SelectOptionItem>(data.map((item) => [item.code, item])),
    [data],
  );

  const selectedCodeSet = useMemo(() => new Set(selectedCodes), [selectedCodes]);

  return (
    <Select
      {...restProps}
      mode="multiple"
      value={selectedCodes}
      showSearch={showSearch}
      allowClear={allowClear}
      placeholder={placeholder}
      options={options}
      optionFilterProp="label"
      maxTagCount="responsive"
      filterOption={(input, option) =>
        normalizeKeyword(String(option?.label ?? '')).includes(normalizeKeyword(input))
      }
      optionRender={(option) => (
        <Flex align="center" gap={8}>
          <Checkbox checked={selectedCodeSet.has(String(option.value))} />
          <span>{String(option.label)}</span>
        </Flex>
      )}
      onChange={(nextCodes) => {
        const normalizedCodes = (nextCodes ?? []) as string[];
        setSelectedCodes(normalizedCodes);
        onChange?.(
          normalizedCodes,
          normalizedCodes
            .map((code) => itemMap.get(code))
            .filter((item): item is SelectOptionItem => item !== undefined),
        );
      }}
    />
  );
}
