'use client';
import { FC, ReactNode, useCallback, useMemo, useRef, useState } from 'react';
import classNames from 'classnames';
import clsx from 'clsx';
import Icon from '@/components/Icon';
import { IOption } from '@/types/IOption';
import { useClickOutside } from '@/hooks/useClickOutside';
import { Checkbox } from '@/components/UI/Checkbox';

interface IClasses {
  root?: string;
  wrapper?: string;
  input?: string;
  dropdown?: string;
  text?: string;
}

interface ISelectProps {
  label?: string | ReactNode;
  placeholder?: string;
  value?: string | string[];
  options?: IOption[];
  onChange?: (_value: IOption['value'] | Array<IOption['value']> | undefined) => void;
  classes?: IClasses;
  withCheckbox?: boolean;
  isMulti?: boolean;
  searchable?: boolean;
}

export const Select: FC<ISelectProps> = ({
  options,
  value,
  placeholder,
  label,
  onChange,
  classes = {},
  withCheckbox,
  isMulti = false,
  searchable,
}) => {
  const [search, setSearch] = useState('');
  const wrapperRef = useRef<HTMLDivElement>(null);
  const searchRef = useRef<HTMLInputElement>(null);
  const [isOpen, setIsOpen] = useState<boolean>(false);
  useClickOutside(wrapperRef, () => setIsOpen(false));

  const handleChange = (newValue: IOption['value']): void => {
    if (isMulti) {
      const prevVal = [...(Array.isArray(value) ? value : [value])].filter((el) => el) as string[];

      if (prevVal.includes(newValue)) {
        onChange?.(prevVal.filter((el) => el !== newValue));
      } else {
        onChange?.([...prevVal, newValue]);
      }
      return;
    }
    setIsOpen(false);
    onChange?.(value === newValue ? undefined : newValue);
  };

  const isEmptyValue = useMemo(() => {
    return Array.isArray(value) ? !value.length : !value;
  }, [value]);

  const handleOpen = useCallback(() => {
    setIsOpen((prev) => !prev);
    setTimeout(() => {
      searchRef.current?.focus();
    }, 100);
  }, []);

  const filtered = useMemo(() => {
    return options?.filter((el) => el.label.includes(search)) || [];
  }, [options, search]);

  return (
    <div className={clsx('w-full', classes.root)}>
      {label && <p className='text-base leading-4 mb-1'>{label}</p>}
      <div
        className={clsx(
          'w-full relative rounded-xl border-[1px] border-light_gray bg-white',
          classes.wrapper,
          {
            'rounded-b-none': isOpen,
          },
        )}
        ref={wrapperRef}
      >
        <div
          className={clsx(classes.input, 'h-[56px] px-4 flex items-center justify-between gap-1')}
          role='button'
          onClick={handleOpen}
        >
          <div
            className={classNames(classes.text, 'text-sm leading-4 w-[calc(100%-12px)]', {
              'text-[#AFAFAF]': !value,
              'text-[#3d3d3d]': !value,
            })}
          >
            <div className='flex gap-1 items-center'>
              <div className='block whitespace-nowrap overflow-hidden text-ellipsis max-w-full'>
                {isOpen ? (
                  <>
                    <input
                      ref={searchRef}
                      type='text'
                      value={search}
                      onChange={(e) => setSearch(e.target.value)}
                      className='outline-none'
                    />
                  </>
                ) : (
                  <>
                    {isEmptyValue ? (
                      placeholder
                    ) : isMulti ? (
                      <div className='flex gap-[2px] items-center'>
                        <div className='block whitespace-nowrap overflow-hidden text-ellipsis max-w-full'>
                          {options?.find((el) => el.value === (value as string[])?.[0])?.label}
                        </div>

                        {(value as string[]).length > 1 && (
                          <div className='bg-primary bg-opacity-10 rounded px-1 py-[2px] h-fit text-xs'>
                            {`+${(value as string[]).length - 1}`}
                          </div>
                        )}
                      </div>
                    ) : (
                      options?.find((el) => el.value === value)?.label
                    )}
                  </>
                )}
              </div>
            </div>
          </div>
          <button type='button'>
            <Icon
              src='/images/icons/icon-chevron-down.svg'
              className={clsx(
                'w-[12px] h-[7px] transition-transform text-primary duration-300',
                isOpen ? 'rotate-180' : 'rotate-0',
              )}
            />
          </button>
        </div>

        {isOpen && (
          <ul
            className={clsx(
              'absolute top-full left-0 w-full bg-white z-10 border-[1px] rounded-xl rounded-t-none border-light_gray border-t-[#D9D9D9] min-h-[64px] max-h-[400px] overflow-y-auto scrollbar select_dropdown',
              classes.dropdown,
              isOpen ? 'visible opacity-100' : 'invisible opacity-0',
            )}
          >
            {filtered.length === 0 ? (
              <li className='px-2 py-4 text-center text-gray-500'>Нет содержимого</li>
            ) : (
              filtered.map((option) => {
                const isChecked = Array.isArray(value)
                  ? value.includes(option.value)
                  : option.value === value;
                return (
                  <li
                    key={option.label}
                    role='button'
                    onClick={() => handleChange(option.value)}
                    className={clsx(
                      ' overflow-hidden px-2 py-4 transition-transform duration-300 ',
                      {
                        'flex items-center gap-3': withCheckbox,
                        'bg-primary bg-opacity-20': isChecked,
                        'opacity-50 pointer-events-none': option.disabled,
                      },
                    )}
                  >
                    {withCheckbox && <Checkbox isActive={isChecked} value={option.value} />}

                    <p className='whitespace-nowrap line-clamp-1 text-base leading-[19px]'>
                      {option.label}
                    </p>
                  </li>
                );
              })
            )}
          </ul>
        )}
      </div>
    </div>
  );
};
