import { useEffect, useRef, useState } from 'react';
import { type FieldErrors, useFormContext } from 'react-hook-form';
import { useLocation, useNavigate } from 'react-router';

import { differenceInSeconds } from 'date-fns';
import { useModal } from '@material-hu/hooks/useModal';
import Container from '@material-hu/mui/Container';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import Alert from '@material-hu/components/design-system/Alert';
import HuDialog from '@material-hu/components/design-system/Dialog';
import TaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import { Title } from '@material-hu/components/design-system/Title';

import useGeneralError from 'src/hooks/useGeneralError';
import { type FormAttributes, type QuestionSubmitData } from 'src/types/forms';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { useFormFileUpload } from '../../forms/FormFileUploadContext';
import useSurveyBranching from '../hooks/useSurveyBranching';
import { type SurveySuccessData } from '../hooks/useSurveyCompletionAndEdit';
import { surveysRoutes } from '../routes';
import {
  buildQuestionMap,
  checkEmptyForm,
  checkEmptyObject,
  formatValues,
  getFilteredValues,
  getQuestionName,
  normalizeDigitalSignValues,
  transformQuestionAnswers,
} from '../utils';

import Footer from './Footer';
import InputFieldWrapper from './inputs/InputFieldWrapper';
import SurveyCompletionSkeleton from './SurveyCompletionSkeleton';
import SurveySuccessScreen from './SurveySuccessScreen';

export type SurveyCompletionFormProps = {
  formDetailData: FormAttributes;
  isLoading: boolean;
  isSubmitting: boolean;
  onSubmit: (body: {
    id: number;
    questions: QuestionSubmitData[];
    fillingTime: number;
  }) => void;
  isFilledAnswer?: boolean;
  successData?: SurveySuccessData | null;
  onShowResponse?: () => void;
  onBackToSurveys?: () => void;
};

const SurveyCompletionForm = ({
  formDetailData,
  isLoading,
  isSubmitting,
  onSubmit,
  isFilledAnswer = false,
  successData,
  onShowResponse,
  onBackToSurveys,
}: SurveyCompletionFormProps) => {
  const { t } = useLokaliseTranslation([
    'forms',
    'general',
    'validations',
    'surveys',
  ]);
  const navigate = useNavigate();
  const location = useLocation();
  const showGeneralError = useGeneralError();

  const scrollableRef = useRef<HTMLDivElement>(null);
  const [startTime] = useState(new Date());

  const { handleSubmit, getValues, resetField, watch } = useFormContext();
  const { isUploadingAny } = useFormFileUpload();

  const {
    currentStep,
    currentSection,
    isFirstStep,
    checkIsLastStep,
    goToNextStep,
    goToPreviousStep,
    resetBranchFields,
  } = useSurveyBranching(
    formDetailData?.steps,
    formDetailData?.hasBranching ?? false,
  );

  const navigateBack = () => {
    if (location.key === 'default') {
      navigate(surveysRoutes.base(), { replace: true });
    } else {
      navigate(-1);
    }
  };

  const {
    modal: unsavedChangesModal,
    showModal: showUnsavedChangesModal,
    closeModal: closeUnsavedChangesModal,
  } = useModal(
    () => (
      <HuDialog
        onClose={closeUnsavedChangesModal}
        title={t('unsaved_changes_title')}
        textBody={t('general:unsaved_changes.description')}
        secondaryButtonProps={{
          children: t('general:cancel'),
          onClick: closeUnsavedChangesModal,
        }}
        primaryButtonProps={{
          children: t('general:unsaved_changes.confirm'),
          onClick: () => {
            closeUnsavedChangesModal();
            navigateBack();
          },
        }}
      />
    ),
    { fullWidth: true, maxWidth: 'sm' },
  );

  // biome-ignore lint/correctness/useExhaustiveDependencies: currentStep is used as a trigger to scroll on step change
  useEffect(() => {
    scrollableRef.current?.scrollTo({ top: 0, behavior: 'instant' });
  }, [currentStep]);

  const submitForm = (values: Record<string, unknown>) => {
    const fillingTime = differenceInSeconds(new Date(), startTime);
    const normalizedValues = normalizeDigitalSignValues(values);
    const questions = formatValues(normalizedValues);
    const questionMap = buildQuestionMap(formDetailData.steps);
    const transformedQuestions = transformQuestionAnswers(
      questions,
      questionMap,
    );

    onSubmit({
      id: formDetailData.id,
      questions: transformedQuestions,
      fillingTime,
    });
  };

  const handleValidSubmit = (values: Record<string, unknown>) => {
    try {
      if (checkIsLastStep(values)) {
        submitForm(values);
        return;
      }

      resetBranchFields(values, resetField);
      goToNextStep(values);
    } catch (err) {
      showGeneralError(err, t('forms:send_form_error'));
    }
  };

  const scrollToFirstError = (errors: FieldErrors) => {
    const container = scrollableRef.current;
    if (!container) return;

    const fieldElements =
      container.querySelectorAll<HTMLElement>('[id^="field-"]');

    for (const element of fieldElements) {
      const fieldName = element.id.slice('field-'.length);
      if (errors[fieldName]) {
        const elementRect = element.getBoundingClientRect();
        const containerRect = container.getBoundingClientRect();
        const scrollTop =
          elementRect.top - containerRect.top + container.scrollTop;

        container.scrollTo({
          top: Math.max(0, scrollTop - 20),
          behavior: 'smooth',
        });
        return;
      }
    }
  };

  const handleNextSection = () => {
    handleSubmit(handleValidSubmit, scrollToFirstError)();
  };

  const handleClose = () => {
    if (successData) {
      navigateBack();
      return;
    }

    const filteredValues = getFilteredValues(getValues());
    const values = Object.values(filteredValues);
    const hasUnsavedData =
      !checkEmptyForm(values) ||
      !checkEmptyObject(filteredValues) ||
      isUploadingAny;

    if (hasUnsavedData) {
      showUnsavedChangesModal();
    } else {
      navigateBack();
    }
  };

  const showAnonymousMessage = formDetailData?.isAnonymous ?? false;
  const isLastStep = checkIsLastStep(watch());

  return (
    <Stack sx={{ width: 1, height: '100vh' }}>
      {unsavedChangesModal}
      <TaskFocusHeader
        title={formDetailData?.title ?? ''}
        onClose={handleClose}
        loading={isLoading}
        slotProps={{
          root: {
            sx: {
              flexShrink: 0,
            },
          },
        }}
      />
      {successData && onShowResponse && onBackToSurveys ? (
        <SurveySuccessScreen
          onShowResponse={onShowResponse}
          onBackToSurveys={onBackToSurveys}
          automaticResponseMessage={formDetailData?.autoMessage}
        />
      ) : (
        <>
          <Stack
            ref={scrollableRef}
            sx={{
              flex: 1,
              overflow: 'auto',
              backgroundColor: ({ palette }) =>
                palette?.new.background.layout.default,
            }}
          >
            <Container
              maxWidth="lg"
              sx={{
                pb: 4,
                pt: 8,
              }}
            >
              {isLoading && <SurveyCompletionSkeleton />}
              {!isLoading && currentSection && (
                <Stack sx={{ gap: 3 }}>
                  {showAnonymousMessage && (
                    <Alert
                      severity="highlight"
                      hasClose
                      title={t('surveys:anonymous_banner_title')}
                      description={t('surveys:anonymous_banner_description')}
                    />
                  )}
                  <Stack sx={{ gap: 2 }}>
                    <Title
                      variant="L"
                      title={currentSection.title}
                      description={currentSection.description}
                    />
                    <Typography
                      variant="globalS"
                      sx={{
                        color: ({ palette }) =>
                          palette.new.text.neutral.lighter,
                        fontStyle: 'italic',
                      }}
                    >
                      {t('validations:required_field_disclaimer')}
                    </Typography>
                  </Stack>
                  {currentSection.questions?.map((question, index) => (
                    <InputFieldWrapper
                      key={`${currentStep}-${index}-${getQuestionName(question)}`}
                      name={`${currentStep}-${index}-${getQuestionName(question)}-${currentSection.id}`}
                      question={question}
                      formFilled={isFilledAnswer}
                    />
                  ))}
                </Stack>
              )}
            </Container>
          </Stack>
          {!isLoading && !isFilledAnswer && (
            <Footer
              isLastStep={isLastStep}
              onNextSection={handleNextSection}
              onGoBackSection={goToPreviousStep}
              isNextSectionDisabled={isUploadingAny}
              isLoading={isSubmitting}
              showBack={!isFirstStep}
            />
          )}
        </>
      )}
    </Stack>
  );
};

export default SurveyCompletionForm;
