import { useCallback, useEffect, useRef } from 'react';
import { Helmet } from 'react-helmet-async';
import { useNavigate } from 'react-router';

import Stack from '@material-hu/mui/Stack';

import TaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import Spinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';
import useSnackbar from '@material-hu/components/design-system/Snackbar';

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

import { Footer } from '../../components/Footer';
import { ModalUnsavedChanges } from '../../components/ModalUnsavedChanges';
import { SideStepper } from '../../components/SideStepper';
import { recruitingRoutes } from '../../routes';
import { JobOfferStatus, Steps } from '../../types';
import { getJobPillLabel, getJobStatusType } from '../../utils';
import { useJobForm } from '../hooks/useJobForm';
import { GeneralConfigStep } from '../JobOfferForm/components/GeneralConfigStep';
import { ProcessStages } from '../JobOfferForm/components/ProcessStages';
import { PublishStep } from '../JobOfferForm/components/PublishStep';
import { ReviewStep } from '../JobOfferForm/components/ReviewStep';

const JobOfferForm = () => {
  const { t } = useLokaliseTranslation('ats');
  const navigate = useNavigate();
  const { enqueueSnackbar } = useSnackbar();

  const scrollableRef = useRef<HTMLDivElement>(null);
  const onScrollToTop = useCallback(() => {
    if (scrollableRef.current) {
      scrollableRef.current.scrollTo({ top: 0, behavior: 'smooth' });
    }
  }, []);

  const {
    generalConfigForm,
    processStagesForm,
    steps,
    footer,
    activeStep,
    setActiveStep,
    isLoadingSave,
    onSave,
    jobId,
    hiringReasons,
    backendHiringPipeline,
    isLoadingBackendHiringPipeline,
    publishForm,
    hasJobBoards,
    isJobPublicDescriptionSaved,
    jobApplicationForm,
    isFetchingApplicationForm,
    applicationFormChanges,
    onApplicationFormChange,
    isApplicationFormDirty,
  } = useJobForm();

  const { modal: unsavedWarningModal } = useUnsavedWarning(
    props => (
      <ModalUnsavedChanges
        {...props}
        onCloseWithoutSaving={() => props.onConfirm()}
        onConfirm={() => {
          onSave(() => props.onConfirm())();
        }}
        isLoading={isLoadingSave}
      />
    ),
    !generalConfigForm.formState.isDirty ||
      !processStagesForm.formState.isDirty ||
      !publishForm.formState.isDirty,
  );

  const title = t('job_offers.new.title');

  const getTopSaveActions = () => {
    if (activeStep === Steps.GENERAL_CONFIG && !jobId) {
      return [];
    }

    const endIcon = isLoadingSave ? <Spinner size={16} /> : undefined;

    if (activeStep === Steps.REVIEW) {
      return [
        {
          key: 'watch_draft',
          children: t('common.watch_draft'),
          onClick: () => navigate(recruitingRoutes.jobDetail(jobId)),
          disabled: !jobId,
          endIcon,
        },
      ];
    }

    const formState = (() => {
      if (activeStep === Steps.PROCESS_STAGES)
        return processStagesForm.formState;
      if (activeStep === Steps.PUBLISH) return publishForm.formState;
      return generalConfigForm.formState;
    })();

    const isDirty =
      formState.isDirty ||
      (activeStep === Steps.PUBLISH && isApplicationFormDirty);
    const { isValid } = formState;

    return [
      {
        key: 'save',
        children: isLoadingSave ? undefined : t('general:save'),
        onClick: onSave((showAlert: boolean) => {
          if (showAlert) {
            enqueueSnackbar({
              variant: 'success',
              title: t('job_offers.alerts.saved_changes'),
            });
          }
        }),
        disabled: !isDirty || !isValid || isLoadingSave,
        endIcon,
      },
    ];
  };

  useEffect(() => {
    if (activeStep >= 0) {
      onScrollToTop();
    }
  }, [onScrollToTop, activeStep]);

  const renderActiveStep = () => {
    if (activeStep === Steps.PROCESS_STAGES && isLoadingBackendHiringPipeline) {
      return <Spinner size={16} />;
    }
    if (activeStep === Steps.GENERAL_CONFIG) {
      return (
        <GeneralConfigStep
          form={generalConfigForm}
          hiringReasons={hiringReasons}
        />
      );
    }
    if (activeStep === Steps.PROCESS_STAGES) {
      return (
        <ProcessStages
          form={processStagesForm}
          jobId={jobId}
          backendHiringPipeline={backendHiringPipeline}
        />
      );
    }
    if (activeStep === Steps.PUBLISH) {
      return (
        <PublishStep
          publishForm={publishForm}
          hasJobBoards={hasJobBoards}
          jobApplicationForm={jobApplicationForm}
          isFetchingApplicationForm={isFetchingApplicationForm}
          applicationFormChanges={applicationFormChanges}
          onApplicationFormChange={onApplicationFormChange}
        />
      );
    }
    return (
      <ReviewStep
        generalConfigForm={generalConfigForm}
        processStagesForm={processStagesForm}
        publishForm={publishForm}
        setActiveStep={setActiveStep}
        hiringReasons={hiringReasons}
        backendHiringPipeline={backendHiringPipeline}
        hasJobBoards={hasJobBoards}
        isJobPublicDescriptionSaved={isJobPublicDescriptionSaved}
        jobApplicationForm={jobApplicationForm}
      />
    );
  };

  return (
    <>
      {unsavedWarningModal}
      <Stack
        sx={{ height: '100vh' }}
        component="form"
        id="jobOfferForm"
        onSubmit={onSave()}
      >
        <Stack sx={{ flex: 0, width: '100%' }}>
          <TaskFocusHeader
            title={title}
            slotProps={{
              title: {
                title,
                withEllipsis: true,
                overflow: 'tooltip',
              },
              root: {
                sx: {
                  '& .MuiStack-root:first-of-type': {
                    mr: 3,
                    '& .MuiStack-root': {
                      maxWidth: 684,
                      mr: 1,
                    },
                  },
                },
              },
              pill: {
                type: getJobStatusType(JobOfferStatus.DRAFT),
              },
            }}
            pillLabel={getJobPillLabel({ jobId, t })}
            onClose={() => navigate(recruitingRoutes.offers())}
            mainActions={getTopSaveActions()}
          />
        </Stack>
        <Stack
          sx={{
            flexDirection: 'row',
            flexGrow: 1,
            flexShrink: 1,
            height: '100%',
            overflow: 'hidden',
          }}
        >
          <SideStepper
            steps={steps}
            activeStep={activeStep}
            onStepClick={step => {
              if (step === activeStep) {
                return;
              } else {
                onSave((showAlert: boolean) => {
                  if (showAlert) {
                    enqueueSnackbar({
                      variant: 'success',
                      title: t('job_offers.alerts.saved_changes'),
                    });
                  }
                  setActiveStep(step);
                })();
              }
            }}
          />
          <Stack
            ref={scrollableRef}
            sx={{
              flexGrow: 1,
              overflowY: 'auto',
              width: '100%',
            }}
          >
            <Stack
              sx={{
                maxWidth: 1040,
                mx: 'auto',
                p: 4,
                width: '100%',
              }}
            >
              {renderActiveStep()}
            </Stack>
          </Stack>
        </Stack>
        <Footer {...footer} />
      </Stack>
    </>
  );
};

const JobOfferWithTheme = () => {
  const HuGoThemeProvider = useHuGoTheme();
  const { t } = useLokaliseTranslation('ats');

  return (
    <>
      <Helmet>
        <title>{formatTitle(t('job_offers.new.title'))}</title>
      </Helmet>
      <HuGoThemeProvider>
        <JobOfferForm />
      </HuGoThemeProvider>
    </>
  );
};

export default JobOfferWithTheme;
