import type { ElementRef } from 'react';
import React, { forwardRef, useMemo, useState, useEffect, useRef } from 'react';
import type { DatePickerProps as ReactDatePickerProps } from 'react-datepicker';
import ReactDatePicker from 'react-datepicker';
import { ko } from 'date-fns/locale';
import { Box, Button, Popover, Typo } from '@/atoms';
import { IconButton } from '../../atoms/icon-button';
import { Flex } from '../../atoms/flex';
import { ChevronLeftIcon, ChevronRightIcon } from '../../icon';
import { Heading } from '../../atoms/heading';

export type DatePickerProps = ReactDatePickerProps & {
  fullWidth?: boolean;
};
type DatePickerRef = ElementRef<typeof ReactDatePicker>;

export const DatePicker = forwardRef<DatePickerRef, DatePickerProps>(
  (props, ref): React.ReactNode => {
    const { fullWidth, ...rest } = props;
    const fullWidthClassName = fullWidth ? 'full-width' : '';
    const [isYearDropdownOpen, setIsYearDropdownOpen] = useState(false);
    const [isMonthDropdownOpen, setIsMonthDropdownOpen] = useState(false);

    const renderCustomHeader = useMemo(() => {
      const getYears = (): number[] => {
        const currentYear = new Date().getFullYear();
        return Array.from(
          { length: currentYear + 5 - 1920 },
          (_, index) => 1920 + index
        ).filter((year) => {
          if (props.minDate && year < props.minDate.getFullYear()) {
            return false;
          }
          if (props.maxDate && year > props.maxDate.getFullYear()) {
            return false;
          }
          return true;
        });
      };

      return getRenderCustomHeader({
        ...props,
        years: getYears(),
        isYearDropdownOpen,
        setIsYearDropdownOpen,
        isMonthDropdownOpen,
        setIsMonthDropdownOpen,
      });
    }, [isMonthDropdownOpen, isYearDropdownOpen, props]);

    return (
      <Flex p="0" width="100%">
        <ReactDatePicker
          dateFormat="yyyy/MM/dd h:mm aa"
          formatWeekDay={(nameOfDay) => {
            return nameOfDay[0];
          }}
          locale={ko}
          nextMonthButtonLabel="다음 달"
          placeholderText="YYYY/MM/DD hh:mm AM/PM"
          popperProps={{ strategy: 'fixed' }}
          previousMonthButtonLabel="이전 달"
          ref={ref}
          renderCustomHeader={renderCustomHeader}
          showPopperArrow={false}
          timeCaption="시간"
          timeFormat="aa h:mm"
          timeIntervals={10}
          {...rest}
          calendarClassName={`tipp_datePicker_calendar ${rest.calendarClassName || ''}`}
          wrapperClassName={`tipp_datePicker ${fullWidthClassName} ${rest.wrapperClassName || ''}`}
        />
      </Flex>
    );
  }
);

DatePicker.displayName = 'DatePicker';

interface DropdownSelectorProps {
  isOpen: boolean;
  onOpenChange: (open: boolean) => void;
  onSelect: (value: number) => void;
  options: number[];
  selectedValue: number | string;
  suffix: string;
}

function DropdownSelector({
  isOpen,
  onOpenChange,
  onSelect,
  options,
  selectedValue,
  suffix,
}: DropdownSelectorProps): React.JSX.Element {
  const scrollContainerRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (isOpen) {
      queueMicrotask(() => {
        const item = scrollContainerRef.current?.querySelector(
          `[data-year-month-dropdown-tiem="${selectedValue}"]`
        );
        if (item) {
          item.scrollIntoView({ behavior: 'instant' });
        }
      });
    }
  }, [isOpen]);

  return (
    <Popover.Root onOpenChange={onOpenChange} open={isOpen} modal>
      <Popover.Trigger>
        <Button variant="ghost">
          <Heading variant="heading4" weight="regular">
            {selectedValue}
            {suffix}
          </Heading>
        </Button>
      </Popover.Trigger>
      <Popover.Content side="bottom">
        <Box
          maxHeight="200px"
          overflowY="auto"
          ref={scrollContainerRef}
          style={{ scrollbarWidth: 'none' }}
        >
          <Flex direction="column" gap="1">
            {options.map((item: number) => (
              <Button
                color="gray"
                data-year-month-dropdown-tiem={item}
                key={item}
                className={'react-datepicker_dropdown_item'}
                onMouseDown={(e) => {
                  e.stopPropagation();
                  e.preventDefault();
                }}
                onClick={() => {
                  onSelect(item);
                }}
                variant="transparent"
              >
                <Typo weight={item === selectedValue ? 'bold' : undefined}>
                  {item}
                  {suffix}
                </Typo>
              </Button>
            ))}
          </Flex>
        </Box>
      </Popover.Content>
    </Popover.Root>
  );
}

const getRenderCustomHeader: (
  props: ReactDatePickerProps & {
    years: number[];
    isYearDropdownOpen: boolean;
    setIsYearDropdownOpen: (show: boolean) => void;
    isMonthDropdownOpen: boolean;
    setIsMonthDropdownOpen: (show: boolean) => void;
  }
) => ReactDatePickerProps['renderCustomHeader'] = (props) => {
  const renderer: ReactDatePickerProps['renderCustomHeader'] = (
    renderCustomHeaderProps
  ) => {
    const {
      date,
      decreaseMonth,
      increaseMonth,
      prevMonthButtonDisabled,
      nextMonthButtonDisabled,
      changeYear,
      changeMonth,
    } = renderCustomHeaderProps;
    const {
      years,
      isYearDropdownOpen,
      setIsYearDropdownOpen,
      isMonthDropdownOpen,
      setIsMonthDropdownOpen,
    } = props;

    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- date가 undefined일 수 있음
    const year = date ? new Date(date).getFullYear() : '-';
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- date가 undefined일 수 있음
    const month = date ? new Date(date).getMonth() + 1 : '-';

    return (
      <Flex align="center"  justify="between" pl="2" pr="2">
        <IconButton
          disabled={prevMonthButtonDisabled}
          onClick={decreaseMonth}
          type="button"
          variant="ghost"
        >
          <ChevronLeftIcon />
        </IconButton>
        <Flex gap="3">
          <DropdownSelector
            isOpen={isYearDropdownOpen}
            onOpenChange={setIsYearDropdownOpen}
            onSelect={(value) => {
              changeYear(value);
              setIsYearDropdownOpen(false);
            }}
            options={years}
            selectedValue={year}
            suffix="년"
          />
          <DropdownSelector
            isOpen={isMonthDropdownOpen}
            onOpenChange={setIsMonthDropdownOpen}
            onSelect={(value) => {
              changeMonth(value - 1);
              setIsMonthDropdownOpen(false);
            }}
            options={Array.from({ length: 12 }, (_, index) => index + 1)}
            selectedValue={month}
            suffix="월"
          />
        </Flex>

        <IconButton
          disabled={nextMonthButtonDisabled}
          onClick={increaseMonth}
          type="button"
          variant="ghost"
        >
          <ChevronRightIcon />
        </IconButton>
      </Flex>
    );
  };
  return renderer;
};

// DatePicker.displayName = 'DatePicker';
