import { useEffect } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useQuery } from 'react-query';

import CloseIcon from '@material-hu/icons/material/Close';
import { IconArrowLeft } from '@material-hu/icons/tabler';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import useCommunityFeature from 'src/hooks/useCommunityFeature';
import { CommunityFeature } from 'src/types/communityFeatures';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { goalsKeys } from '../../queries';
import { getGoalCycle, getGoalFormulaChain } from '../../services';
import {
  type Goal,
  GoalPriorityTypes,
  GoalProgressTypes,
  GoalTypes,
  GoalVisibilityTypes,
} from '../../types';
import { isBinaryProgressType } from '../../utils';
import { getDefaultValues, isGoalFormValid } from '../utils/goalForm';

import NewGoalFooter from './NewGoalFooter';
import NewGoalFormFields from './NewGoalFormFields';
import NewGoalVisibilityNote from './NewGoalVisibilityNote';

type NewGoalFormProps = {
  goalId: number | null;
  goal: Goal | undefined;
  isGoalLoading: boolean;
  isTissur: boolean;
  isSouthbay: boolean;
  cycleIdFromRouter: number | null;
  onSave: (formValues: Goal) => void;
  onClose: (formValues: Goal) => void;
};

function NewGoalForm({
  goalId,
  goal,
  isGoalLoading,
  isTissur,
  isSouthbay,
  cycleIdFromRouter,
  onSave,
  onClose,
}: NewGoalFormProps) {
  const { t } = useLokaliseTranslation('goals');
  const hideBinaryValueType = useCommunityFeature(
    CommunityFeature.GOALS_HIDE_BINARY_VALUE_TYPE,
  );
  const hidePrioritySelector = useCommunityFeature(
    CommunityFeature.GOALS_HIDE_PRIORITY_SELECTOR,
  );

  const form = useForm<Goal>({
    defaultValues: {
      title: '',
      hasDescription: false,
      description: '',
      valueType: GoalProgressTypes.BINARY,
      visibility: GoalVisibilityTypes.PRIVATE,
      type: GoalTypes.INDIVIDUAL,
      priority: GoalPriorityTypes.LOW,
      responsible: [],
      startDate: new Date(),
      endDate: undefined,
      goalCycleId: cycleIdFromRouter || 0,
      startingValue: '',
      objectiveValue: '',
      valueUnit: '',
      minValue: '',
      maxValue: '',
      status: '',
      formulaChain: null,
      goalCycle: {},
    },
    mode: 'onChange',
  });

  useEffect(() => {
    if (!goal) return;
    const loadAndReset = async () => {
      const values = getDefaultValues(goal);
      if (goal.formulaChainId) {
        try {
          const res = await getGoalFormulaChain(goal.formulaChainId);
          const formula = res.data;
          values.formulaChain = { value: formula.id, label: formula.title };
        } catch {
          values.formulaChain = null;
        }
      }
      form.reset(values);
    };
    void loadAndReset();
  }, [goal, form]);

  useEffect(() => {
    if (hideBinaryValueType && !goalId) {
      form.setValue('valueType', GoalProgressTypes.PERCENTAGE);
    }
  }, [hideBinaryValueType, goalId, form]);

  useEffect(() => {
    if (hidePrioritySelector && !goalId) {
      form.setValue('priority', GoalPriorityTypes.MEDIUM);
    }
  }, [hidePrioritySelector, goalId, form]);

  const goalCycleIdFromForm = useWatch({
    control: form.control,
    name: 'goalCycleId',
  });

  useQuery(
    goalsKeys.cycle(goalCycleIdFromForm),
    () => {
      if (goalCycleIdFromForm == null || goalCycleIdFromForm <= 0) {
        throw new Error('goalCycleId is required when goal cycle query runs');
      }
      return getGoalCycle(goalCycleIdFromForm);
    },
    {
      select: r => r.data,
      enabled: !!goalCycleIdFromForm && goalCycleIdFromForm > 0,
      onSuccess: data => {
        form.setValue('goalCycle', data);
      },
    },
  );

  const hasDescription = useWatch({
    control: form.control,
    name: 'hasDescription',
  });
  const valueType = useWatch({ control: form.control, name: 'valueType' });
  const responsible = useWatch({ control: form.control, name: 'responsible' });
  const startingValue = useWatch({
    control: form.control,
    name: 'startingValue',
  });
  const objectiveValue = useWatch({
    control: form.control,
    name: 'objectiveValue',
  });

  const isBinary = isBinaryProgressType(valueType);

  const handleFormSave = () => {
    onSave(form.getValues());
  };

  return (
    <FormProvider {...form}>
      <Stack
        id="review-layout"
        sx={{
          backgroundColor: 'new.background.layout.default',
          height: '100%',
          overflowY: 'scroll',
        }}
      >
        <Stack
          sx={{
            flexDirection: 'row',
            alignItems: 'center',
            justifyContent: 'space-between',
            backgroundColor: 'new.background.layout.tertiary',
            px: 2,
            py: 1.5,
            gap: 1,
            position: 'sticky',
            top: 0,
            left: 0,
            zIndex: 200,
          }}
        >
          <Stack
            sx={{
              flexDirection: 'row',
              alignItems: 'center',
              gap: 1,
            }}
          >
            <IconButton
              aria-label="back"
              sx={{ p: 0 }}
              onClick={() => onClose(form.getValues())}
            >
              <IconArrowLeft />
            </IconButton>
            <Typography
              variant="globalL"
              fontWeight="fontWeightSemiBold"
              color="new.text.neutral.default"
            >
              {t(goalId ? 'list.edit' : 'list.create')}
            </Typography>
          </Stack>
          <IconButton
            aria-label="close"
            sx={{ p: 0 }}
            onClick={() => onClose(form.getValues())}
          >
            <CloseIcon />
          </IconButton>
        </Stack>

        {!isGoalLoading && (
          <>
            <Stack sx={{ p: 3, justifyContent: 'center' }}>
              <Stack sx={{ mt: 2, mx: 'auto', width: 600 }}>
                <NewGoalFormFields
                  isTissur={isTissur}
                  isSouthbay={isSouthbay}
                  hasDescription={Boolean(hasDescription)}
                  onToggleDescription={() => {
                    const newHasDescription = !hasDescription;
                    form.setValue('hasDescription', newHasDescription, {
                      shouldDirty: true,
                    });
                    if (!newHasDescription) {
                      form.setValue('description', '', { shouldDirty: false });
                    }
                  }}
                />
                <NewGoalVisibilityNote />
              </Stack>
            </Stack>
            <NewGoalFooter
              disabled={
                !form.formState.isValid ||
                !isGoalFormValid(
                  responsible,
                  isBinary,
                  startingValue,
                  objectiveValue,
                )
              }
              onSave={handleFormSave}
            />
          </>
        )}
      </Stack>
    </FormProvider>
  );
}

export default NewGoalForm;
