/** biome-ignore-all lint/correctness/useHookAtTopLevel: false positive hook is used in useDrawerV2 */
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation, useQueryClient } from 'react-query';

import { type AxiosError } from 'axios';
import { isEqual } from 'lodash-es';
import Stack from '@material-hu/mui/Stack';

import Alert from '@material-hu/components/design-system/Alert';
import { type DrawerProps } from '@material-hu/components/design-system/Drawer';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { ApplicantPersonalInfoForm } from '../../../components/ApplicantPersonalInfoForm';
import { JobDetailsForm } from '../../../components/JobDetailsForm';
import { RECRUITING_API_ERROR_CODES } from '../../../constants';
import { useUploadFile } from '../../../hooks/useUploadFile';
import { applicantsKeys, jobKeys } from '../../../queries';
import { recruitingRoutes } from '../../../routes';
import {
  updateJobCandidateApplication,
  uploadCandidateCV,
} from '../../../services';
import {
  type AddCandidateError,
  type ApplicationSource,
  type ApplicationStage,
  type CandidateFormWithFileCard,
  type JobDetailCandidateForm,
} from '../../../types';
import {
  applicantDetailCandidateFormResolver,
  getInitialValuesFromApplication,
  parseCandidateError,
} from '../../JobApplicationDetail/utils';

type UseApplicantUpdateDrawerContentProps = {
  onClose: () => void;
  jobId: number;
  applicationSources: ApplicationSource[];
  applicationId: number;
  stages: ApplicationStage[];
};

type DrawerOpenProps = {
  initialValues: Partial<JobDetailCandidateForm>;
};

export const useApplicantUpdateDrawerContent =
  ({
    onClose,
    jobId,
    applicationSources,
    applicationId,
    stages,
  }: UseApplicantUpdateDrawerContentProps) =>
  ({ initialValues }: DrawerOpenProps) => {
    const HuGoThemeProvider = useHuGoTheme();
    const { t } = useLokaliseTranslation([
      'ats',
      'validations',
      'errors',
      'general',
    ]);
    const { enqueueSnackbar } = useHuSnackbar();
    const queryClient = useQueryClient();
    const existingCandidateAlertRef = useRef<HTMLDivElement>(null);
    const [showExistingCandidateAlert, setShowExistingCandidateAlert] =
      useState<{ jobId: number; applicationId: number } | null>(null);

    const scrollToExistingCandidateAlert = () => {
      existingCandidateAlertRef.current?.scrollIntoView({ behavior: 'smooth' });
    };

    const handleOpenExistingCandidateAlert = () => {
      if (
        showExistingCandidateAlert?.jobId &&
        showExistingCandidateAlert?.applicationId
      ) {
        window.open(
          recruitingRoutes.JobApplicationDetail(
            showExistingCandidateAlert.jobId,
            showExistingCandidateAlert.applicationId,
          ),
          '_blank',
          'noopener,noreferrer',
        );
      }
    };

    const handleClose = (shouldResetForm = false) => {
      if (shouldResetForm) {
        resetForm();
      }
      onClose();
      setShowExistingCandidateAlert(null);
    };

    const resolver = useMemo(
      () => (values: Partial<JobDetailCandidateForm>) =>
        applicantDetailCandidateFormResolver(values, t),
      [t],
    );

    const initialValuesRef = useRef(initialValues);

    const form = useForm<Partial<JobDetailCandidateForm>>({
      mode: 'onChange',
      defaultValues: initialValues,
      resolver,
    });

    const resetForm = useCallback(() => {
      form.reset(initialValues, {
        keepIsSubmitted: false,
        keepDirty: false,
        keepErrors: false,
      });
    }, [form, initialValues]);

    useEffect(() => {
      // Deep object comparison using isEqual from lodash
      if (!isEqual(initialValuesRef.current, initialValues) && applicationId) {
        initialValuesRef.current = initialValues;
        resetForm();
      }
    }, [initialValues, applicationId, resetForm]);

    const [isUploadingCV, setIsUploadingCV] = useState(false);

    const { onUpload } = useUploadFile({
      uploadService: uploadCandidateCV,
      onSettled: () => setIsUploadingCV(true),
      onSuccess: () => setIsUploadingCV(false),
      onError: () => setIsUploadingCV(false),
    });

    const { mutate: editCandidate, isLoading: isUpdatingCandidate } =
      useMutation(
        (values: CandidateFormWithFileCard) =>
          updateJobCandidateApplication(jobId, applicationId, values),
        {
          onMutate: () => {
            setShowExistingCandidateAlert(null);
          },
          onSuccess: response => {
            onClose();
            const { application } = response.data;
            form.reset(
              getInitialValuesFromApplication({
                application,
                applicationSources,
              }),
              {
                keepIsSubmitted: false,
                keepDirty: false,
                keepErrors: false,
              },
            );

            queryClient.invalidateQueries(jobKeys.detail(jobId));
            queryClient.invalidateQueries(
              applicantsKeys.applicationDetail(jobId, applicationId),
            );
            queryClient.invalidateQueries(
              applicantsKeys.formAnswers(jobId, applicationId),
            );

            enqueueSnackbar({
              title: t('job_candidates.alerts.candidate_updated'),
              variant: 'success',
            });
          },
          onError: (error: AxiosError<AddCandidateError>) => {
            if (
              error?.response?.data?.code ===
              RECRUITING_API_ERROR_CODES.DUPLICATE_ENTITY
            ) {
              setShowExistingCandidateAlert(
                parseCandidateError(error.response.data.details ?? ''),
              );
              form.setError('phone', { message: '' });
              // Time for the alert ref to be set
              setTimeout(() => {
                scrollToExistingCandidateAlert();
              }, 0);
              return;
            } else {
              enqueueSnackbar({
                title: t('general:error_title'),
                variant: 'error',
              });
            }
          },
        },
      );

    const onSubmit = form.handleSubmit(
      (values: Partial<JobDetailCandidateForm>) => {
        editCandidate(values as CandidateFormWithFileCard);
      },
    );

    const isLoading = isUploadingCV || isUpdatingCandidate;

    return {
      children: (
        <HuGoThemeProvider>
          <Stack
            sx={{
              gap: 3,
            }}
          >
            <Alert
              severity="warning"
              title={t(
                'job_application.tabs.application.uneditable_fields_disclaimer',
              )}
              hasClose={false}
              sx={{
                '& .MuiAlert-message span': {
                  letterSpacing: '0.1px',
                },
              }}
            />
            <FormProvider {...form}>
              <ApplicantPersonalInfoForm onUploadFile={onUpload} />
              <JobDetailsForm
                applicationSources={applicationSources}
                stages={stages}
                type="edit"
              />
            </FormProvider>
            {showExistingCandidateAlert && (
              <Stack ref={existingCandidateAlertRef}>
                <Alert
                  severity="warning"
                  description={t(
                    'job_candidates.alerts.candidate_add_error.description',
                  )}
                  title={t('job_candidates.alerts.candidate_add_error.title')}
                  hasClose={false}
                  action={{
                    text: t('job_candidates.alerts.candidate_add_error.action'),
                    onClick: () => handleOpenExistingCandidateAlert(),
                  }}
                  sx={{
                    alignItems: 'center',
                    '& .MuiAlert-message': {
                      maxWidth: 350,
                    },
                  }}
                />
              </Stack>
            )}
          </Stack>
        </HuGoThemeProvider>
      ),
      title: t('job_application.tabs.application.application_form_edit'),
      primaryButtonProps: {
        children: t('general:save_changes'),
        onClick: onSubmit,
        disabled:
          !form.formState.isValid || !form.formState.isDirty || isLoading,
        loading: isLoading,
      },
      secondaryButtonProps: {
        children: t('general:cancel'),
        onClick: () => handleClose(true),
      },
      onClose: () => handleClose(false),
      disableEscapeKeyDown: true,
    } as DrawerProps;
  };
