import { useEffect, useMemo, useRef, useState } from 'react';
import { Helmet } from 'react-helmet-async';
import { useMutation, useQueryClient } from 'react-query';
import { Navigate, useNavigate } from 'react-router';

import { useDrawerV2 } from '@material-hu/hooks/useDrawerV2';
import { useModal } from '@material-hu/hooks/useModal';
import { IconConfetti } from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';

import TaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import { type PillsProps } from '@material-hu/components/design-system/Pills';
import useSnackbar from '@material-hu/components/design-system/Snackbar';
import StateCard from '@material-hu/components/design-system/StateCard';
import Title from '@material-hu/components/design-system/Title';

import useAuth from 'src/contexts/JWTContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import LoadingScreen from 'src/components/LoadingScreen';

import { applicantsKeys } from '../../queries';
import { recruitingRoutes } from '../../routes';
import {
  deleteApplicationStageFile,
  deleteApplicationStageNote,
} from '../../services';
import {
  type ApplicationResponse,
  type ApplicationStage as ApplicationStageType,
  ApplicationStatus,
  JobOfferStatus,
  StageTypes,
} from '../../types';
import { getProcessStageNameFromBackend } from '../../utils';
import { useApplicationDetail } from '../hooks/useApplicationDetail';
import { useApplicationFormAnswers } from '../hooks/useApplicationFormAnswers';
import { useApplicationSources } from '../hooks/useApplicationSources';
import { useJob } from '../hooks/useJob';
import { useRejectionReasons } from '../hooks/useRejectionReasons';
import { useRouteId } from '../hooks/useRouteId';

import { ApplicationStage } from './components/ApplicationStage';
import { ContactInfoAndActions } from './components/ContactInfoAndActions';
import { DeleteFileModal } from './components/DeleteFileModal';
import { DeleteNoteModal } from './components/DeleteNoteModal';
import { HiredOrRejectedAlert } from './components/HiredOrRejectedAlert';
import { MoveApplicantForwardModal } from './components/MoveApplicantForwardModal';
import { RejectApplicantModal } from './components/RejectApplicantModal';
import { SideContentTabs } from './components/SideContentTabs';
import { useActionDrawers } from './hooks/useActionDrawers';
import { useFilesDrawerContent } from './hooks/useFilesDrawerContent';
import { useHireModal } from './hooks/useHireModal';
import { useMoveApplicantStageDrawerContent } from './hooks/useMoveApplicantStageDrawerContent';
import { useNotesDrawerContent } from './hooks/useNotesDrawerContent';
import { getInitialValuesFromApplication } from './utils';

const JobApplicationDetail = ({
  application,
  fullName,
}: {
  application: ApplicationResponse;
  fullName: string;
}) => {
  const { t } = useLokaliseTranslation(['ats', 'files', 'general']);
  const navigate = useNavigate();
  const sideContentRef = useRef<HTMLDivElement>(null);
  const queryClient = useQueryClient();
  const { enqueueSnackbar } = useSnackbar();
  const { user } = useAuth();
  const { id, firstName, lastName } = user || {};
  const userData = {
    id,
    firstName,
    lastName,
  };
  const [expandedStageIds, setExpandedStageIds] = useState<number[]>([]);

  const pillProps = useMemo(() => {
    const result = {
      type: 'neutral' as PillsProps['type'],
      label: '',
    };
    switch (application.status) {
      case ApplicationStatus.REJECTED:
        result.type = 'error';
        result.label = t('application_stage_status.rejected_one');
        return result;
      case ApplicationStatus.HIRED:
        result.type = 'success';
        result.label = t('application_stage_status.hired_one');
        return result;
      case ApplicationStatus.PENDING:
        result.type = 'info';
        result.label = t('application_stage_status.pending');
        return result;
      case ApplicationStatus.PAUSED:
        result.type = 'warning';
        result.label = t('application_stage_status.paused');
        return result;
      default:
        result.type = 'neutral';
        result.label = getProcessStageNameFromBackend(
          application.currentPipelineStageId,
          application?.stages?.map(stage => ({
            ...stage,
            id: stage.pipelineStageId,
          })) || [],
          t,
        );
        return result;
    }
  }, [
    application.status,
    application.currentPipelineStageId,
    application.stages,
    t,
  ]);

  const { jobOffer } = useJob(application.jobId);
  const { applicationSources, isLoadingApplicationSources } =
    useApplicationSources();
  const { data: jobApplicationFormAnswers, isLoading: isLoadingFormAnswers } =
    useApplicationFormAnswers(application.jobId, application.id);

  const profilePictureUrl = (() => {
    const basicInfo = jobApplicationFormAnswers?.sections.find(
      s => s.code === 'basic_info',
    );
    const picField = basicInfo?.fields.find(
      f => f.field.code === 'profile_picture',
    );
    const val = picField?.answer?.value;
    return val && typeof val === 'object' && 'url' in val
      ? (val.url as string)
      : undefined;
  })();

  const { editApplicationDrawer } = useActionDrawers({
    application,
    applicationSources,
  });
  const { rejectionReasons } = useRejectionReasons();

  const filesDrawer = useDrawerV2(
    useFilesDrawerContent({
      onClose: () => filesDrawer.closeDrawer(),
      applicationId: application.id,
      jobId: application.jobId,
    }),
  );

  const notesDrawer = useDrawerV2(
    useNotesDrawerContent({
      onClose: () => notesDrawer.closeDrawer(),
      applicationId: application.id,
      jobId: application.jobId,
    }),
  );

  const moveApplicantForwardDrawer = useDrawerV2(
    useMoveApplicantStageDrawerContent({
      onClose: () => moveApplicantForwardDrawer.closeDrawer(),
      jobId: application.jobId,
      stages: application.stages,
    }),
  );

  const { mutate: deleteFile, isLoading: isLoadingDeleteFile } = useMutation({
    mutationFn: ({ fileId, stageId }: { fileId: number; stageId: number }) =>
      deleteApplicationStageFile({
        jobId: application.jobId,
        applicationId: application.id,
        fileId,
        stageId,
      }),
    onSuccess: () => {
      enqueueSnackbar({
        title: t('files:deleted_file'),
        variant: 'success',
      });
      handleCloseDeleteFileModal();
      queryClient.invalidateQueries(
        applicantsKeys.applicationDetail(application.jobId, application.id),
      );
    },
    onError: () => {
      enqueueSnackbar({
        title: t('common.error_files.error_delete'),
        variant: 'error',
      });
    },
  });

  const {
    closeModal: closeDeleteStageFileModal,
    showModal: showDeleteStageFileModal,
    modal: deleteStageFileModal,
  } = useModal<{ fileId: number; stageId: number }>(props => (
    <DeleteFileModal
      {...props}
      isLoading={isLoadingDeleteFile}
      onConfirm={({ fileId, stageId }) => {
        if (!fileId || !stageId) return;
        deleteFile({
          fileId,
          stageId,
        });
      }}
      onClose={handleCloseDeleteFileModal}
    />
  ));

  const handleCloseDeleteFileModal = () => {
    closeDeleteStageFileModal();
  };

  const handleRejectOrHireSuccess = () => {
    setExpandedStageIds([]);
  };

  const {
    modal: modalRejectApplicant,
    showModal: showRejectApplicantModal,
    closeModal: closeRejectApplicantModal,
  } = useModal<{ stage: ApplicationStageType }>(props => (
    <RejectApplicantModal
      {...props}
      rejectionReasons={rejectionReasons}
      jobId={application.jobId}
      onClose={handleCloseRejectApplicantModal}
      onSuccess={handleRejectOrHireSuccess}
    />
  ));

  const handleCloseRejectApplicantModal = () => {
    closeRejectApplicantModal();
  };

  const currentStage = application.stages.find(
    stage => stage.pipelineStageId === application.currentPipelineStageId,
  );

  const {
    modal: modalMoveApplicantForward,
    showModal: showMoveApplicantForwardModal,
    closeModal: closeMoveApplicantForwardModal,
  } = useModal<{ stage: ApplicationStageType }>(props => (
    <MoveApplicantForwardModal
      {...props}
      stages={application.stages}
      jobId={application.jobId}
      onClose={handleCloseMoveApplicantForwardModal}
    />
  ));

  const handleCloseMoveApplicantForwardModal = () => {
    closeMoveApplicantForwardModal();
  };

  const { mutate: deleteNote, isLoading: isLoadingDeleteNote } = useMutation(
    ({ stageId }: { stageId: number }) =>
      deleteApplicationStageNote({
        jobId: application.jobId,
        applicationId: application.id,
        stageId,
      }),
    {
      onSuccess: () => {
        enqueueSnackbar({
          title: t('job_application.notes.delete.success'),
          variant: 'success',
        });
        handleCloseDeleteNoteModal();
        queryClient.invalidateQueries(
          applicantsKeys.applicationDetail(application.jobId, application.id),
        );
      },
      onError: () => {
        enqueueSnackbar({
          title: t('general:error_title'),
          variant: 'error',
        });
      },
    },
  );

  const {
    closeModal: closeDeleteNoteModal,
    showModal: showDeleteNoteModal,
    modal: deleteNoteModal,
  } = useModal<{ stageId: number }>(props => (
    <DeleteNoteModal
      {...props}
      isLoading={isLoadingDeleteNote}
      onClose={handleCloseDeleteNoteModal}
      onConfirm={({ stageId }) => {
        if (!stageId) return;
        deleteNote({ stageId });
      }}
    />
  ));

  const handleCloseDeleteNoteModal = () => {
    closeDeleteNoteModal();
  };

  const { modal: hireModal, showModal: showHireModal } = useHireModal({
    jobId: application.jobId,
    applicationId: application.id,
    applicantName: `${application.firstName} ${application.lastName}`,
    stage: currentStage,
    onSuccess: handleRejectOrHireSuccess,
  });

  useEffect(() => {
    if (currentStage && application.status === ApplicationStatus.ACTIVE) {
      setExpandedStageIds([currentStage.id]);
    }
  }, [currentStage, application.status]);

  const isOfferStage =
    !!application.stages.find(
      stage =>
        (stage.stageType === StageTypes.OFFER ||
          stage.stageType === StageTypes.OFFER_ACCEPTED) &&
        stage.pipelineStageId === application.currentPipelineStageId,
    ) || false;

  return (
    <Stack
      sx={{
        height: '100vh',
        minHeight: 0,
        overflow: 'hidden',
      }}
    >
      {/* Header sticky section */}
      <Stack
        sx={{
          flexShrink: 0,
          position: 'sticky',
          top: 0,
          zIndex: 1,
        }}
      >
        <TaskFocusHeader
          title={fullName}
          slotProps={{
            extraActions: {
              closeDropdownOnClick: true,
            },
            root: {
              sx: {
                '& .MuiStack-root:first-of-type': {
                  mr: 3,
                  '& .MuiStack-root': {
                    maxWidth: 684,
                    mr: 1,
                  },
                },
                py: 2,
              },
            },
            title: {
              title: fullName,
              withEllipsis: true,
              overflow: 'tooltip',
            },
            pill: {
              ...pillProps,
              sx: {
                maxWidth: 238,
              },
            },
          }}
          pillLabel={pillProps.label}
          onBack={() => navigate(recruitingRoutes.jobOffer(application.jobId))}
          onClose={() => navigate(recruitingRoutes.jobOffer(application.jobId))}
          extraActions={[]}
        />
        <ContactInfoAndActions
          isOfferStage={isOfferStage}
          isJobActive={jobOffer?.status === JobOfferStatus.OPEN}
          jobName={jobOffer?.name || ''}
          application={application}
          profilePictureUrl={profilePictureUrl}
          onRejectClick={() => {
            showRejectApplicantModal({ stage: currentStage });
          }}
          isLastStage={currentStage?.stageType === StageTypes.OFFER_ACCEPTED}
          onForwardClick={() => {
            if (currentStage?.stageType === StageTypes.OFFER_ACCEPTED) {
              showHireModal();
              return;
            }
            showMoveApplicantForwardModal({ stage: currentStage });
          }}
          onMoveToStageClick={() => {
            moveApplicantForwardDrawer.showDrawer({ stage: currentStage });
          }}
          onEditClick={() => {
            editApplicationDrawer.showDrawer({
              initialValues: getInitialValuesFromApplication({
                application,
                applicationSources,
              }),
            });
          }}
        />
      </Stack>
      {/* Main content section */}
      <Stack
        sx={{
          flex: 1,
          flexDirection: 'row',
          height: '100%',
          minHeight: 0,
          overflow: 'hidden',
        }}
      >
        <Stack
          sx={{
            backgroundColor: theme =>
              theme.palette.new.background.layout.default,
            borderRight: theme =>
              `1px solid ${theme.palette.new.border.neutral.default}`,
            flexGrow: 1,
            gap: 3,
            height: '100%',
            minHeight: 0,
            overflowY: 'auto',
            p: 3,
          }}
        >
          {(application.status === ApplicationStatus.REJECTED ||
            application.status === ApplicationStatus.HIRED) && (
            <HiredOrRejectedAlert
              application={{
                ...application,
                jobOpening:
                  application.jobOpening ||
                  jobOffer?.jobOpenings?.[0] ||
                  undefined,
              }}
            />
          )}
          <Title
            title={t('job_offers.new.stages.title')}
            variant="M"
          />
          <Stack sx={{ gap: 3, width: '100%', flexGrow: 1 }}>
            {application.stages.map(stage => (
              <ApplicationStage
                cv={
                  stage.stageType === StageTypes.PROFILE_REVIEW
                    ? application.resume
                    : null
                }
                key={stage.id}
                stage={stage}
                isCurrentStage={
                  stage.pipelineStageId === application.currentPipelineStageId
                }
                onAddFilesClick={({ files, stageId }) => {
                  filesDrawer.showDrawer({
                    files,
                    stageId,
                  });
                }}
                onAddNotesClick={({ stageId }) => {
                  notesDrawer.showDrawer({
                    stageId,
                    user: userData,
                  });
                }}
                onNoteClick={({ note, stageId }) => {
                  notesDrawer.showDrawer({
                    note,
                    stageId,
                    user: userData,
                  });
                }}
                onDeleteNoteClick={({ stageId }) => {
                  showDeleteNoteModal({ stageId });
                }}
                onDeleteFileClick={({ file, stageId }) => {
                  showDeleteStageFileModal({ fileId: file.id, stageId });
                }}
                jobId={application.jobId}
                onHireClick={() => {
                  showHireModal();
                }}
                onForwardClick={() => {
                  showMoveApplicantForwardModal({ stage: stage });
                }}
                onRejectClick={({ stage: stg }) => {
                  showRejectApplicantModal({ stage: stg });
                }}
                user={userData}
                applicationStatus={application.status}
                isExpanded={expandedStageIds.includes(stage.id)}
                onExpandChange={({ id: stageId, isExpanded }) => {
                  setExpandedStageIds(prev =>
                    isExpanded
                      ? [...prev, stageId]
                      : prev.filter(preId => preId !== stageId),
                  );
                }}
              />
            ))}
            {application.status === ApplicationStatus.HIRED && (
              <StateCard
                title={t('job_application.actions.hire.card.title')}
                description={t('job_application.actions.hire.card.description')}
                icon={IconConfetti}
                variant="primary"
                primaryAction={{
                  label: t('job_application.actions.hire.card.cta'),
                  onClick: () => {
                    navigate('/users');
                  },
                }}
                slotProps={{
                  card: { sx: { p: 1 } },
                }}
              />
            )}
          </Stack>
        </Stack>
        <Stack
          ref={sideContentRef}
          sx={{
            backgroundColor: theme =>
              theme.palette.new.background.layout.tertiary,
            flexShrink: 0,
            gap: 3,
            height: '100%',
            minHeight: 0,
            overflowY: 'auto',
            p: 3,
            width: 496,
          }}
        >
          <SideContentTabs
            application={application}
            applicationSources={applicationSources}
            isLoading={isLoadingApplicationSources || isLoadingFormAnswers}
            jobApplicationFormAnswers={jobApplicationFormAnswers}
            scrollableRef={sideContentRef}
          />
        </Stack>
      </Stack>
      {editApplicationDrawer.drawer}
      {filesDrawer.drawer}
      {notesDrawer.drawer}
      {moveApplicantForwardDrawer.drawer}
      {deleteStageFileModal}
      {modalRejectApplicant}
      {modalMoveApplicantForward}
      {deleteNoteModal}
      {hireModal}
    </Stack>
  );
};

const JobApplicationDetailWithTheme = () => {
  const HuGoThemeProvider = useHuGoTheme();
  const { t } = useLokaliseTranslation('ats');
  const jobId = useRouteId({
    fallbackRoute: recruitingRoutes.offers(),
    routeParam: 'jobOfferId',
  });
  const applicantId = useRouteId({
    fallbackRoute: recruitingRoutes.jobOffer(jobId),
    routeParam: 'applicantId',
  });
  const { data: application, isLoading } = useApplicationDetail(
    jobId,
    applicantId,
  );

  if (!jobId || !applicantId) return null;

  if (!application && !isLoading) {
    return (
      <Navigate
        to={recruitingRoutes.jobOffer(jobId)}
        replace
      />
    );
  }

  const fullName = `${application?.firstName} ${application?.lastName}`;

  return (
    <>
      <Helmet>
        <title>
          {formatTitle(
            application
              ? `${t('common.applicant_one')} - ${fullName}`
              : t('common.job_one'),
          )}
        </title>
      </Helmet>
      <HuGoThemeProvider>
        {isLoading && <LoadingScreen />}
        {application && !isLoading && (
          <JobApplicationDetail
            application={application}
            fullName={fullName}
          />
        )}
      </HuGoThemeProvider>
    </>
  );
};

export default JobApplicationDetailWithTheme;
