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

import { round } from 'lodash-es';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { getFormTemplatesScore } from 'src/services/performanceService';
import {
  type ReviewDirection,
  type ScoreDirectionItem,
  type ScoreFormValues,
} from 'src/types/performance';
import { useLokaliseTranslation } from 'src/utils/i18n';

import CenteredCircularProgress from 'src/components/CircularProgress';

import { reviewsKeys } from '../../../queries';
import { useCycleEditRestrictions } from '../../context/useCycleEditRestrictions';

import DirectionWeights from './components/DirectionWeights/DirectionWeights';
import {
  getInitialDirectionWeightsOptions,
  mergeDirectionsWithUpdatedWeightDetails,
} from './components/utils';

type DirectionWeightsStepProps = {
  cycleId: number;
  templateIds?: number[];
};

const DirectionWeightsStep = ({
  cycleId,
  templateIds = [],
}: DirectionWeightsStepProps) => {
  const { t } = useLokaliseTranslation('performance');
  const { disableRestrictedFields } = useCycleEditRestrictions();
  const HuGoThemeProvider = useHuGoTheme();

  const scoreForm = useFormContext<ScoreFormValues>();

  const {
    isLoading: isLoadingScoreData,
    data: scoreData,
    isFetching: isFetchingScoreData,
  } = useQuery(
    [...reviewsKeys.formTemplatesScore(cycleId), [...templateIds].sort()],
    () => getFormTemplatesScore(cycleId).then(res => res.data),
    {
      enabled: !!cycleId,
      select: data => {
        return {
          initialDirectionWeightsOptions: getInitialDirectionWeightsOptions(
            data.directions,
            data.possibleDirectionsWithScore || [],
            data.excludedDirections,
          ),
          possibleDirectionsMap: new Map(
            data.possibleDirectionsWithScore?.map(direction => [
              direction.evaluationType,
              direction,
            ]),
          ),
          scoreDetails: data.scoreDetails,
        };
      },
      onSuccess: data => {
        const currentDirections = scoreForm.getValues('directions');

        if (!currentDirections || currentDirections.length === 0) {
          scoreForm.setValue(
            'directions',
            data.initialDirectionWeightsOptions.filter(
              option => option.enabled,
            ),
            { shouldDirty: false },
          );
          scoreForm.setValue(
            'scoreDetails',
            {
              ...data.scoreDetails,
              qualitativeResultRanges:
                data.scoreDetails?.qualitativeResultRanges ?? [],
            },
            { shouldDirty: false },
          );
          return;
        }

        const mergedDirections = mergeDirectionsWithUpdatedWeightDetails(
          currentDirections,
          data.initialDirectionWeightsOptions,
        );
        scoreForm.setValue('directions', mergedDirections, {
          shouldDirty: true,
        });
      },
    },
  );

  const enabledDirections = useWatch({
    control: scoreForm.control,
    name: 'directions',
  });

  const totalDirectionsWeight = useMemo(() => {
    return round(
      enabledDirections.reduce((sum, direction) => sum + direction.weight, 0),
      2,
    );
  }, [enabledDirections]);

  if (isLoadingScoreData || isFetchingScoreData || !scoreData) {
    return <CenteredCircularProgress centered />;
  }

  const handleDirectionWeightToggle = (
    evaluationType: ReviewDirection,
    enabled: boolean,
  ) => {
    const possibleDirection =
      scoreData.possibleDirectionsMap.get(evaluationType);
    if (disableRestrictedFields || !possibleDirection) return;
    let newDirections: ScoreDirectionItem[] = [];
    if (enabled) {
      newDirections = [
        ...enabledDirections,
        {
          evaluationType,
          weight: 0,
          weightDetails: possibleDirection.weightDetails,
        },
      ];
    } else {
      newDirections = enabledDirections.filter(
        d => d.evaluationType !== evaluationType,
      );
    }
    scoreForm.setValue('directions', newDirections, {
      shouldDirty: true,
    });
  };

  const handleSetDirectionWeights = (
    evaluationType: ReviewDirection,
    weight: number,
  ) => {
    const newDirections = enabledDirections.map(dir => {
      if (dir.evaluationType === evaluationType) {
        return { ...dir, weight };
      }
      return dir;
    });
    scoreForm.setValue('directions', newDirections, {
      shouldDirty: true,
    });
  };

  return (
    <HuGoThemeProvider>
      <Stack
        sx={{
          gap: 2,
          pb: 2,
        }}
      >
        <Stack
          sx={{
            flexDirection: 'row',
            justifyContent: 'space-between',
          }}
        >
          <Typography variant="h4">
            {t('form.cycle_steps.score.title')}
          </Typography>
        </Stack>

        <Typography
          variant="body2"
          sx={{ pb: 2 }}
        >
          {t('form.cycle_steps.score.subtitle')}
        </Typography>
        <DirectionWeights
          enabledDirections={enabledDirections}
          initialDirectionWeightsOptions={
            scoreData.initialDirectionWeightsOptions
          }
          onDirectionWeightChange={handleSetDirectionWeights}
          onDirectionWeightToggle={handleDirectionWeightToggle}
          totalDirectionsWeight={totalDirectionsWeight}
        />
      </Stack>
    </HuGoThemeProvider>
  );
};

export default DirectionWeightsStep;
