import { useEffect, useMemo } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import { useQuery } from 'react-query';
import { useParams } from 'react-router';

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

import HuFormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import HuFormDatePicker from '@material-hu/components/design-system/Inputs/DatePicker/form';
import HuFormInputSelect from '@material-hu/components/design-system/Inputs/Select/form';

import { useAuth } from 'src/contexts/JWTContext';
import useCommunityFeature from 'src/hooks/useCommunityFeature';
import { CommunityFeature } from 'src/types/communityFeatures';
import { dateIsBefore } from 'src/utils/date';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { goalsKeys } from '../../queries';
import { getGoalCycles } from '../../services';
import { type GoalCycle, GoalProgressTypes } from '../../types';
import {
  getGoalEndDatePickerMinDate,
  isBinaryProgressType,
  isGoalCycleFinishedStatus,
  isGoalNew,
  isNumberProgressType,
  isTissurInstance,
  utcCalendarDayToFormDate,
} from '../../utils';

import CriticalityButtonGroup from './CriticalityButtonGroup';
import ResponsiblePicker from './ResponsiblePicker/ResponsiblePicker';
import ValueInputsAndFormula from './ValueInputsAndFormula';

export const EditDetails = () => {
  const { t } = useLokaliseTranslation('goals');
  const { id } = useParams();

  const { control, setValue } = useFormContext();
  const { goalCycleId, startDate, endDate } = useWatch({ control });
  const valueType = useWatch({ control, name: 'valueType' });
  const goalCycle = useWatch({ control, name: 'goalCycle' });
  const goalId = id ? parseInt(id) : null;

  const { instance } = useAuth();
  const instanceId = instance?.id;
  const isNewGoal = isGoalNew(goalId);

  const cyclePagination = { page: 0, limit: 50 };
  const { data: cycles } = useQuery(
    [goalsKeys.cycles(cyclePagination)],
    () => getGoalCycles(cyclePagination),
    {
      keepPreviousData: true,
      select: response => response.data.items,
    },
  );

  const cyclesList = useMemo(() => {
    const mappedCycles =
      cycles?.map((c: GoalCycle) => ({
        label: c.name,
        value: c.id,
        startDate: c.startDate,
        endDate: c.endDate,
        status: c.status,
      })) || [];

    if (!isNewGoal) return mappedCycles;

    return mappedCycles.filter(
      cycle => !isGoalCycleFinishedStatus(cycle.status),
    );
  }, [cycles, isNewGoal]);

  const isBinary = isBinaryProgressType(valueType);
  const isNumber = isNumberProgressType(valueType);
  const isTissur = isTissurInstance(instanceId);
  const hideBinaryValueType = useCommunityFeature(
    CommunityFeature.GOALS_HIDE_BINARY_VALUE_TYPE,
  );
  const hidePrioritySelector = useCommunityFeature(
    CommunityFeature.GOALS_HIDE_PRIORITY_SELECTOR,
  );

  const progressTypes = useMemo(() => {
    const all = Object.keys(GoalProgressTypes).map(pType => ({
      value: pType,
      label: t(`new.${pType.toLowerCase()}`),
    }));
    if (hideBinaryValueType) {
      return all.filter(p => p.value !== GoalProgressTypes.BINARY);
    }
    return all;
  }, [t, hideBinaryValueType]);

  const limitOptions = () => {
    if (!goalId) return progressTypes;
    if (isBinary)
      return progressTypes.filter(p => p.value === GoalProgressTypes.BINARY);
    if (!isBinary)
      return progressTypes.filter(p => p.value !== GoalProgressTypes.BINARY);
  };

  const cycle = cyclesList?.find(c => c.value === goalCycleId);

  const cycleStart = useMemo(
    () =>
      cycle?.startDate ? utcCalendarDayToFormDate(cycle.startDate) : undefined,
    [cycle?.startDate],
  );
  const cycleEnd = useMemo(
    () =>
      cycle?.endDate ? utcCalendarDayToFormDate(cycle.endDate) : undefined,
    [cycle?.endDate],
  );

  useEffect(() => {
    const rawStart = goalCycle?.startDate;
    const rawEnd = goalCycle?.endDate;
    if (!rawStart || !rawEnd) return;

    const startNorm = utcCalendarDayToFormDate(rawStart);
    const endNorm = utcCalendarDayToFormDate(rawEnd);

    if (
      dateIsBefore(startDate, startNorm) ||
      dateIsBefore(endNorm, startDate)
    ) {
      setValue('startDate', startNorm);
    }
    if (
      !endDate ||
      dateIsBefore(endNorm, endDate) ||
      dateIsBefore(endDate, startNorm)
    ) {
      setValue('endDate', endNorm);
    }
  }, [goalCycle, startDate, endDate, setValue]);

  const endBoundForStartMax = endDate ?? cycleEnd;
  const endPickerMinDate = getGoalEndDatePickerMinDate(startDate, cycleStart);

  return (
    <Stack sx={{ gap: 3 }}>
      <HuFormInputSelect
        name="goalCycleId"
        inputProps={{
          options: cyclesList || [],
          label: t('new.goal_cycle'),
          placeholder: '',
        }}
      />
      <Stack sx={{ gap: 3 }}>
        <HuFormInputSelect
          name="valueType"
          inputProps={{
            label: t('new.how_measure_progress'),
            options: limitOptions() || [],
            disabled: !!(goalId && isBinary),
          }}
        />
        {!isBinary && <ValueInputsAndFormula />}
      </Stack>
      {isTissur && isNumber && (
        <HuFormInputClassic
          name="valueUnit"
          inputProps={{
            label: t('new.measure_unit'),
            size: 'small',
            fullWidth: true,
            maxLength: 15,
          }}
        />
      )}
      <Stack sx={{ flexDirection: 'row', gap: 2 }}>
        <HuFormDatePicker
          name="startDate"
          inputProps={{
            label: t('start_date'),
            minDate: cycleStart,
            maxDate: endBoundForStartMax,
            fullWidth: true,
          }}
        />
        <HuFormDatePicker
          name="endDate"
          inputProps={{
            label: t('ending_date'),
            minDate: endPickerMinDate,
            maxDate: cycleEnd,
            fullWidth: true,
          }}
        />
      </Stack>
      <ResponsiblePicker isNewGoal={isNewGoal} />
      {!hidePrioritySelector && (
        <Stack sx={{ mb: 2, gap: 1 }}>
          <Typography
            variant="globalS"
            fontWeight="fontWeightSemiBold"
            color="new.text.neutral.default"
          >
            {t('new.criticality')}
          </Typography>
          <CriticalityButtonGroup />
        </Stack>
      )}
    </Stack>
  );
};

export default EditDetails;
