import { type FC, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { IconButton, Stack, Typography } from '@mui/material';
import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react';
import {
  addDays,
  addMonths,
  differenceInDays,
  lastDayOfMonth,
  nextMonday,
  nextSunday,
  previousMonday,
  previousSunday,
} from 'date-fns';

import Dropdown from '../../design-system/Dropdown';
import DatePickersV6Provider from '../../design-system/Inputs/Base/DatePickersV6Provider';
import RadioButton from '../../design-system/RadioButton/RadioButton';

import CustomRangeSelector from './components/CustomRangeSelector';
import {
  type DatePeriodSelectorProps,
  type PeriodButton,
  Periods,
  type PeriodsWithoutCustom,
} from './types';
import { checkDateReference } from './utils';

const DatePeriodSelector: FC<DatePeriodSelectorProps> = props => {
  const {
    fromDate,
    handleFromChange,
    handleToChange,
    toDate,
    sx,
    initialPeriod = Periods.DAILY,
    dateFormatter,
    minMaxDatesDifference,
    currentDate = new Date(),
    showDateReference = false,
  } = props;
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
  const [periodType, setPeriodType] = useState(initialPeriod);
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
  const { t } = useTranslation('material_hu_only');

  const periodButtons: PeriodButton[] = [
    {
      type: Periods.DAILY,
      text: t('date_period_selector.daily'),
    },
    {
      type: Periods.WEEKLY,
      text: t('date_period_selector.weekly'),
    },
    {
      type: Periods.MONTHLY,
      text: t('date_period_selector.monthly'),
    },
  ];

  const periodIndicator = {
    [Periods.DAILY]: dateFormatter(fromDate),
    [Periods.WEEKLY]: t('date_period_selector.date_from_to', {
      from: dateFormatter(fromDate),
      to: dateFormatter(toDate),
    }),
    [Periods.MONTHLY]: dateFormatter(fromDate, 'MMMM yyyy').toUpperCase(),
    [Periods.CUSTOM]: t('date_period_selector.date_from_to', {
      from: dateFormatter(fromDate),
      to: dateFormatter(toDate),
    }),
  };

  const handlePeriodSelection: Record<PeriodsWithoutCustom, () => void> = {
    [Periods.DAILY]: () => {
      handleToChange(fromDate);
    },
    [Periods.WEEKLY]: () => {
      const weekStart =
        fromDate.getDay() === 1 ? fromDate : previousMonday(fromDate);
      handleFromChange(weekStart);
      handleToChange(nextSunday(weekStart));
    },
    [Periods.MONTHLY]: () => {
      handleFromChange(
        new Date(fromDate.getFullYear(), fromDate.getMonth(), 1),
      );
      handleToChange(lastDayOfMonth(fromDate));
    },
  };

  const handleNextPeriod = {
    [Periods.DAILY]: () => {
      handleFromChange(addDays(fromDate, 1));
      handleToChange(addDays(fromDate, 1));
    },
    [Periods.WEEKLY]: () => {
      const weekStart = nextMonday(fromDate);
      handleFromChange(weekStart);
      handleToChange(nextSunday(weekStart));
    },
    [Periods.MONTHLY]: () => {
      const nextMonth = addMonths(fromDate, 1);
      handleFromChange(nextMonth);
      handleToChange(lastDayOfMonth(nextMonth));
    },
    [Periods.CUSTOM]: () => {
      const daysDifference = differenceInDays(toDate, fromDate);
      handleFromChange(addDays(fromDate, daysDifference));
      handleToChange(addDays(toDate, daysDifference));
    },
  }[periodType];

  const handlePreviousPeriod = {
    [Periods.DAILY]: () => {
      handleFromChange(addDays(fromDate, -1));
      handleToChange(addDays(fromDate, -1));
    },
    [Periods.WEEKLY]: () => {
      handleFromChange(previousMonday(fromDate));
      handleToChange(previousSunday(toDate));
    },
    [Periods.MONTHLY]: () => {
      const previousMonth = addMonths(fromDate, -1);
      handleFromChange(previousMonth);
      handleToChange(lastDayOfMonth(previousMonth));
    },
    [Periods.CUSTOM]: () => {
      const daysDifference = differenceInDays(toDate, fromDate);
      handleFromChange(addDays(fromDate, -daysDifference));
      handleToChange(addDays(toDate, -daysDifference));
    },
  }[periodType];

  const handleOpen = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const referenceIndicator =
    showDateReference && periodType === Periods.DAILY
      ? `${checkDateReference(currentDate, fromDate)}`
      : '';
  const selectedDateInPeriod = `${referenceIndicator} ${periodIndicator[periodType]}`;

  return (
    <DatePickersV6Provider>
      <Stack
        sx={{
          alignItems: 'stretch',
          justifyContent: 'center',
          flexDirection: 'row',
          gap: 3,
          ...sx,
        }}
      >
        <Dropdown
          label={t(`date_period_selector.${periodType.toLowerCase()}`)}
          position="center"
          open={isDropdownOpen}
          onOpen={() => {
            setIsDropdownOpen(true);
          }}
          onClose={() => {
            setIsDropdownOpen(false);
          }}
          sx={{ '.MuiButtonBase-root': { height: '100%' } }}
        >
          {periodButtons.map(button => (
            <RadioButton
              key={button.type}
              label={button.text}
              isActive={periodType === button.type}
              onClick={() => {
                setPeriodType(button.type);
                handlePeriodSelection[button.type]();
                setIsDropdownOpen(false);
              }}
              stackSx={{ p: 2 }}
            />
          ))}
        </Dropdown>
        <Stack
          sx={{
            alignItems: 'center',
            alignSelf: 'center',
            backgroundColor: ({ palette }) =>
              palette.new.background.elements.default,
            border: ({ palette }) =>
              `1px solid ${palette.new.border.neutral.default}`,
            borderRadius: 1,
            flexDirection: 'row',
            justifyContent: 'space-between',
            gap: 3,
            px: 1.5,
            py: 1,
            width: 336,
          }}
        >
          <IconButton
            title={t('date_period_selector.previous')}
            onClick={e => {
              e.stopPropagation();
              handlePreviousPeriod();
            }}
            sx={{ p: 0 }}
            disableRipple
          >
            <IconChevronLeft />
          </IconButton>
          <Typography
            variant="globalS"
            sx={{
              cursor: 'pointer',
              '&:hover': {
                textDecoration: 'underline',
              },
            }}
            onClick={handleOpen}
          >
            {selectedDateInPeriod}
          </Typography>
          <CustomRangeSelector
            anchorElement={anchorEl}
            handleClose={handleClose}
            fromDate={fromDate}
            toDate={toDate}
            handleFromDateChange={handleFromChange}
            handleToDateChange={handleToChange}
            updatePeriodType={setPeriodType}
            minMaxDatesDifference={minMaxDatesDifference}
          />
          <IconButton
            title={t('date_period_selector.next')}
            onClick={e => {
              e.stopPropagation();
              handleNextPeriod();
            }}
            sx={{ p: 0 }}
            disableRipple
          >
            <IconChevronRight />
          </IconButton>
        </Stack>
      </Stack>
    </DatePickersV6Provider>
  );
};

export default DatePeriodSelector;
