import { useState, useEffect, useMemo } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';

import { IconArrowBack } from '@material-hu/icons/tabler';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import { type SxProps } from '@material-hu/mui/styles';

import Typography from '@material-hu/mui/Typography/Typography';

import FormTimePicker from '@material-hu/components/composed-components/TimePicker/form';
import FormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';

import { useLokaliseTranslation } from 'src/utils/i18n';
import { preventNonNumberInput } from 'src/utils/inputUtils';
import { WEEKDAYS } from 'src/utils/timeUtils';

import { areDaysConsecutive } from '../../../utils';
import {
  type HoursMinutesValue,
  HourCategorizationFields,
  HourCategorizationOperators,
  HourCategorizationValidDays,
  HourCategorizationValidScheduledHours,
  HourCategorizationValueTypes,
} from '../../types';

type FormValuesWithRules = {
  rules: Array<{
    conditions: Array<{
      value: HoursMinutesValue | null | undefined;
    }>;
  }>;
};

import DayListSelector from './DayListSelector';
import FormDropdown from './FormDropdown';
import Tooltip from '@material-hu/components/design-system/Tooltip';

type ConditionValueProps = {
  ruleIndex: number;
  conditionIndex: number;
  field: HourCategorizationFields | undefined;
  operator: HourCategorizationOperators | undefined;
  sx?: SxProps;
};

const ConditionValue = ({
  ruleIndex,
  conditionIndex,
  field,
  operator,
  sx,
}: ConditionValueProps) => {
  const { t } = useLokaliseTranslation([
    'time_tracker',
    'time_tracking_common',
    'general',
    'work_schedules',
  ]);
  const { setValue, watch, setFocus, getValues } = useFormContext();
  const [showDayListSelector, setShowDayListSelector] = useState(false);

  const valueName = `rules.${ruleIndex}.conditions.${conditionIndex}.value`;
  const hoursFieldName = `${valueName}.hours`;
  const valueTypeName = `rules.${ruleIndex}.conditions.${conditionIndex}.valueType`;
  const currentValueType = watch(valueTypeName);
  const currentValue = useWatch({
    name: valueName,
    exact: true,
  });

  const OPTIONS_HOURS = [
    {
      label: t('time_tracker:categorized_hours.scheduled_hours'),
      value: HourCategorizationValueTypes.SCHEDULED_HOURS,
    },
    {
      label: t('time_tracker:categorized_hours.number_of_hours'),
      value: HourCategorizationValueTypes.NUMBER_OF_HOURS,
    },
  ];

  const OPTIONS_EQUALS = [
    {
      label: t('time_tracker:categorized_hours.specific_days'),
      value: HourCategorizationValueTypes.DAY_LIST,
    },
    {
      label: t('time_tracking_common:vacations_holidays'),
      value: HourCategorizationValueTypes.HOLIDAY,
    },
    {
      label: t('time_tracking_common:day_off'),
      value: HourCategorizationValueTypes.REST_DAY,
    },
    {
      label: t('work_schedules:workday'),
      value: HourCategorizationValueTypes.WORK_DAY,
    },
    {
      label: t('time_tracking_common:permit_day'),
      value: HourCategorizationValueTypes.LEAVE_DAY,
    },
  ];

  const formatSelectedDaysLabel = useMemo(() => {
    if (
      currentValueType !== HourCategorizationValueTypes.DAY_LIST ||
      !Array.isArray(currentValue) ||
      currentValue.length === 0
    ) {
      return undefined; // Return undefined to use the placeholder
    }

    const days = currentValue.filter(
      (day): day is HourCategorizationValidDays =>
        Object.values(HourCategorizationValidDays).includes(day),
    );

    if (days.length === 0) {
      return undefined;
    }

    const sortedDays = [...days].sort(
      (a, b) => WEEKDAYS.indexOf(a) - WEEKDAYS.indexOf(b),
    );

    if (areDaysConsecutive(sortedDays)) {
      const firstDay = t(`general:week_days_short.${sortedDays[0]}`);
      const lastDay = t(
        `general:week_days_short.${sortedDays[sortedDays.length - 1]}`,
      );
      return `${t('time_tracker:categorized_hours.specific_days')}: ${firstDay} ${t('general:to')} ${lastDay}`;
    } else {
      const dayAbbreviations = sortedDays.map(day =>
        t(`general:week_days_short.${day}`),
      );
      return `${t('time_tracker:categorized_hours.specific_days')}: ${dayAbbreviations.join(', ')}`;
    }
  }, [currentValue, currentValueType, t]);

  // Effect to automatically open the DayListSelector when DAY_LIST is selected
  useEffect(() => {
    setShowDayListSelector(
      operator === HourCategorizationOperators.EQUALS &&
        currentValueType === HourCategorizationValueTypes.DAY_LIST,
    );
  }, [currentValueType]);

  // Effect to focus the hours input when NUMBER_OF_HOURS is selected
  useEffect(() => {
    if (
      (operator === HourCategorizationOperators.GREATER_THAN ||
        operator === HourCategorizationOperators.LESS_THAN) &&
      currentValueType === HourCategorizationValueTypes.NUMBER_OF_HOURS
    ) {
      setFocus(hoursFieldName);
    }
  }, [currentValueType, operator, hoursFieldName, setFocus]);

  const handleResetCondition = () => {
    const operatorName = `rules.${ruleIndex}.conditions.${conditionIndex}.operator`;
    setValue(operatorName, undefined, { shouldDirty: true });
    setValue(valueTypeName, undefined, { shouldDirty: true });
    setValue(valueName, undefined, { shouldDirty: true });
  };

  const validateHoursMinutes = (_value: string): boolean => {
    const formValues = getValues() as FormValuesWithRules;
    const parentValue =
      formValues.rules?.[ruleIndex]?.conditions?.[conditionIndex]?.value;
    const h = Number(parentValue?.hours) || 0;
    const m = Number(parentValue?.minutes) || 0;
    return h > 0 || m > 0;
  };

  if (
    field === HourCategorizationFields.TIME_RANGE &&
    operator === HourCategorizationOperators.EQUALS
  ) {
    const startTimeName = `${valueName}[0]`;
    const endTimeName = `${valueName}[1]`;
    if (currentValueType !== HourCategorizationValueTypes.TIME_RANGE) {
      // Operator is EQUALS, so we set the value type to TIME_RANGE
      setValue(valueTypeName, HourCategorizationValueTypes.TIME_RANGE, {
        shouldDirty: true,
      });
    }

    return (
      <Stack
        sx={{
          flex: '1 1 0',
          minWidth: 0,
          flexDirection: 'row',
          alignItems: 'center',
          gap: 1,
          ...sx,
        }}
      >
        <FormTimePicker
          name={startTimeName}
          rules={{ required: true }}
          inputProps={{
            placeholder: '00:00',
            size: 'small',
            noIcon: true,
          }}
        />
        <Typography variant="globalXS">{t('general:to')}</Typography>
        <FormTimePicker
          name={endTimeName}
          rules={{ required: true }}
          inputProps={{
            placeholder: '00:00',
            size: 'small',
            noIcon: true,
          }}
        />
        <Tooltip
          title={t('general:undo')}
          direction="bottom"
        >
          <IconButton
            variant="tertiary"
            onClick={handleResetCondition}
            aria-label={t('general:undo')}
            size="small"
          >
            <IconArrowBack />
          </IconButton>
        </Tooltip>
      </Stack>
    );
  }

  if (
    operator === HourCategorizationOperators.GREATER_THAN ||
    operator === HourCategorizationOperators.LESS_THAN
  ) {
    if (currentValueType === HourCategorizationValueTypes.NUMBER_OF_HOURS) {
      const hoursName = `${valueName}.hours`;
      const minutesName = `${valueName}.minutes`;

      return (
        <Stack
          sx={{
            flex: '1 1 0',
            minWidth: 0,
            flexDirection: 'row',
            alignItems: 'center',
            gap: 1,
            ...sx,
          }}
        >
          <FormInputClassic
            name={hoursName}
            rules={{ validate: validateHoursMinutes }}
            inputProps={{
              fullWidth: true,
              placeholder: t('general:hour_other'),
              hasCounter: false,
              showClear: false,
              type: 'number',
              inputMode: 'numeric',
              maxLength: 2,
              onKeyDown: preventNonNumberInput,
              sx: {
                '& .MuiInputBase-root': {
                  height: '36px',
                  backgroundColor: theme =>
                    theme.palette.new.background.layout.tertiary,
                },
              },
            }}
          />
          <FormInputClassic
            name={minutesName}
            rules={{ validate: validateHoursMinutes }}
            inputProps={{
              fullWidth: true,
              placeholder: t('general:minute_other'),
              hasCounter: false,
              showClear: false,
              type: 'number',
              inputMode: 'numeric',
              maxLength: 2,
              onKeyDown: preventNonNumberInput,
              sx: {
                '& .MuiInputBase-root': {
                  height: '36px',
                  backgroundColor: theme =>
                    theme.palette.new.background.layout.tertiary,
                },
              },
            }}
          />
          <IconButton
            variant="tertiary"
            onClick={() => {
              setValue(valueTypeName, undefined, { shouldDirty: true });
              setValue(valueName, undefined, { shouldDirty: true });
            }}
            aria-label={t('general:undo')}
            size="small"
            sx={{ alignSelf: 'center' }}
          >
            <IconArrowBack />
          </IconButton>
        </Stack>
      );
    }

    return (
      <FormDropdown
        name={valueTypeName}
        required
        sx={{ flex: '1 1 0', minWidth: 0, ...sx }}
        placeholder={t('time_tracker:categorized_hours.value_type')}
        options={OPTIONS_HOURS}
        onOptionSelect={value => {
          if (value === HourCategorizationValueTypes.SCHEDULED_HOURS) {
            setValue(valueName, HourCategorizationValidScheduledHours.DAILY, {
              shouldDirty: true,
            });
          }
        }}
      />
    );
  }

  if (operator === HourCategorizationOperators.EQUALS) {
    const isDayListSelected =
      currentValueType === HourCategorizationValueTypes.DAY_LIST;
    if (isDayListSelected) {
      return (
        <FormDropdown
          name={valueTypeName}
          required
          placeholder={t('time_tracker:categorized_hours.specific_days')}
          customLabel={formatSelectedDaysLabel}
          sx={{ flex: '1 1 0', minWidth: 0, ...sx }}
          onOpen={() => {
            setShowDayListSelector(true);
          }}
        >
          {(anchorEl, onClose, keepOpen) =>
            showDayListSelector && (
              <DayListSelector
                ruleIndex={ruleIndex}
                conditionIndex={conditionIndex}
                anchorEl={anchorEl}
                onClose={() => {
                  setShowDayListSelector(false);
                  onClose();
                }}
                onBack={() => {
                  setShowDayListSelector(false);
                  keepOpen();
                }}
              />
            )
          }
        </FormDropdown>
      );
    }

    return (
      <FormDropdown
        name={valueName}
        required
        customLabel={isDayListSelected ? formatSelectedDaysLabel : undefined}
        options={OPTIONS_EQUALS}
        placeholder={t('time_tracker:categorized_hours.value_type')}
        sx={{ flex: '1 1 0', minWidth: 0, ...sx }}
        onOptionSelect={value => {
          if (value === HourCategorizationValueTypes.DAY_LIST) {
            setValue(valueTypeName, HourCategorizationValueTypes.DAY_LIST, {
              shouldDirty: true,
            });
            setValue(valueName, undefined, { shouldDirty: true });
            setShowDayListSelector(true);
            return true; // Keep dropdown open to show DayListSelector
          } else {
            setValue(valueName, value, { shouldDirty: true });
            setValue(valueTypeName, HourCategorizationValueTypes.DAY_TYPE, {
              shouldDirty: true,
            });
            return false;
          }
        }}
      />
    );
  }

  return (
    <FormDropdown
      name={valueName}
      required
      options={[]}
      placeholder={t('general:value')}
      disabled={true}
      sx={{ flex: '1 1 0', minWidth: 0, ...sx }}
    />
  );
};

export default ConditionValue;
