import { 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 Stack from '@material-hu/mui/Stack';

import Alert from '@material-hu/components/design-system/Alert';
import Drawer from '@material-hu/components/design-system/Drawer';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';
import { useDrawerLayer } from '@material-hu/components/layers/Drawers';

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 { jobKeys } from '../../../../queries';
import { recruitingRoutes } from '../../../../routes';
import {
  createJobCandidateApplication,
  uploadCandidateCV,
} from '../../../../services';
import {
  type AddCandidateError,
  type ApplicationSource,
  type CandidateFormWithFileCard,
  type HiringPipelineWithCountResponse,
  type JobDetailCandidateForm,
} from '../../../../types';
import {
  getJobDetailCandidateFormDefaultValues,
  jobDetailAddCandidateFormResolver,
} from '../../../../utils';
import { parseCandidateError } from '../../../JobApplicationDetail/utils';

type AddCandidateDrawerContentProps = {
  jobId?: number | null;
  stages: HiringPipelineWithCountResponse[];
  applicationSources: ApplicationSource[];
};

export const AddCandidateDrawerContent = ({
  jobId,
  stages,
  applicationSources,
}: AddCandidateDrawerContentProps) => {
  const HuGoThemeProvider = useHuGoTheme();
  const { t } = useLokaliseTranslation(['ats', 'validations', 'errors']);
  const { enqueueSnackbar } = useHuSnackbar();
  const queryClient = useQueryClient();
  const { closeDrawer } = useDrawerLayer();
  const existingCandidateAlertRef = useRef<HTMLDivElement>(null);
  const [showExistingCandidateAlert, setShowExistingCandidateAlert] = useState<{
    jobId: number;
    applicationId: number;
  } | null>(null);

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

  const defaultValues = useMemo(
    () =>
      getJobDetailCandidateFormDefaultValues({
        stages,
        sources: applicationSources,
        t,
      }),
    [stages, applicationSources, t],
  );

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

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

  useEffect(() => {
    form.reset(defaultValues);
  }, [defaultValues, form]);

  const handleClose = () => {
    form.reset(defaultValues, { keepIsSubmitted: false });
    setShowExistingCandidateAlert(null);
    closeDrawer();
  };

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

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

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

  const { mutate: addCandidate, isLoading: isAddingCandidate } = useMutation({
    mutationFn: (values: CandidateFormWithFileCard) => {
      if (!jobId) {
        throw new Error('Job ID is required');
      }
      return createJobCandidateApplication(jobId, values);
    },
    onMutate: () => {
      setShowExistingCandidateAlert(null);
    },
    onSuccess: () => {
      form.reset(defaultValues, { keepIsSubmitted: false });
      closeDrawer();
      queryClient.invalidateQueries(jobKeys.detail(jobId));
      enqueueSnackbar({
        title: t('job_candidates.alerts.candidate_added'),
        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: '' });
        setTimeout(() => {
          scrollToExistingCandidateAlert();
        }, 0);
      }
    },
  });

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

  const isLoading = isUploadingCV || isAddingCandidate;

  return (
    <>
      <Drawer.Header
        title={t('job_candidates.new.title')}
        onClose={handleClose}
      />
      <Drawer.Body>
        <HuGoThemeProvider>
          <Stack sx={{ gap: 3 }}>
            <FormProvider {...form}>
              <ApplicantPersonalInfoForm onUploadFile={onUpload} />
              <JobDetailsForm
                applicationSources={applicationSources}
                type="create"
                stages={stages}
              />
            </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: handleOpenExistingCandidate,
                  }}
                  sx={{
                    alignItems: 'center',
                    '& .MuiAlert-message': {
                      maxWidth: 350,
                    },
                  }}
                />
              </Stack>
            )}
          </Stack>
        </HuGoThemeProvider>
      </Drawer.Body>
      <Drawer.Actions
        primaryButtonProps={{
          children: t('general:add_alt'),
          onClick: onSubmit,
          disabled:
            !form.formState.isValid || !form.formState.isDirty || isLoading,
          loading: isLoading,
        }}
        secondaryButtonProps={{
          children: t('general:cancel'),
          onClick: handleClose,
        }}
      />
    </>
  );
};
