import { type FC, useMemo } from 'react';
import { useFormContext } from 'react-hook-form';
import { type UseMutateFunction } from 'react-query';

import { type AxiosResponse } from 'axios';
import { IconX } from '@material-hu/icons/tabler';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import { ThemeProvider } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';
import { createHuGoTheme } from '@material-hu/theme/hugo';
import { type FileAsset } from '@material-hu/types/attachments';

import Button from '@material-hu/components/design-system/Buttons/Button';

import {
  type FormSection,
  type FormSectionBody,
  type SectionComponent,
  type SectionContent,
  type ServiceItem,
} from 'src/pages/dashboard/serviceManagement/types';
import { generateFormProgressData } from 'src/pages/dashboard/serviceManagement/utils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import useSnackbar from '../../../hooks/useSnackbar';
import { usePdfCompletion } from '../contexts/PdfFormCompletionProvider';

import ExpandableInfoSidebar from './ExpandableInfoSidebar';
import PdfControls from './PdfControls';
import PdfDocumentForm from './PdfDocumentForm';
import { isValidFieldAnswer, isValidPdfFormCompletion } from './utils/utils';

type Props = {
  pdfFileAsset: FileAsset;
  currentForm: SectionContent | null;
  serviceItem: ServiceItem | undefined;
  updateSectionMutation: UseMutateFunction<
    AxiosResponse<FormSection, any>,
    unknown,
    FormSectionBody,
    unknown
  >;
  onCloseForm: () => void;
  loadingSendForm: boolean;
};

const PdfFormCompletion: FC<Props> = ({
  currentForm,
  pdfFileAsset,
  serviceItem,
  onCloseForm,
  updateSectionMutation,
  loadingSendForm,
}) => {
  const { t } = useLokaliseTranslation('service_management');
  const { showSnackbar } = useSnackbar();
  const { getValues } = useFormContext();
  const { setShowErrors, scrollToFieldPosition } = usePdfCompletion();

  const handleSubmitForm = () => {
    if (!currentForm) return;
    const formValues = getValues();

    if (!isValidPdfFormCompletion(formValues, currentForm)) {
      setShowErrors(true);
      showSnackbar({
        title: t('incomplete_pdf_fields_title'),
        description: t('incomplete_pdf_fields_description'),
        variant: 'error',
      });
      // Find first invalid field by (page asc, y asc). First invalid field in reading order.
      const invalidComponents = (currentForm.components || [])
        .filter(c => {
          const value = formValues[c.nameId];
          // reuse field validator from utils
          return !isValidFieldAnswer(
            c.type,
            value,
            c.validations,
            c.content.required,
          );
        })
        .sort((a, b) => {
          const ap = a.pdfLayout?.page || Number.MAX_SAFE_INTEGER;
          const bp = b.pdfLayout?.page || Number.MAX_SAFE_INTEGER;
          if (ap !== bp) return ap - bp;
          const ay = a.pdfLayout?.y ?? Number.POSITIVE_INFINITY;
          const by = b.pdfLayout?.y ?? Number.POSITIVE_INFINITY;
          return ay - by;
        });

      const first = invalidComponents[0];
      if (first?.pdfLayout?.page) {
        const page = first.pdfLayout.page;
        const yRel = first.pdfLayout.y ?? 0;
        scrollToFieldPosition(page, yRel, 'smooth');
      }
      return;
    }

    setShowErrors(false);
    const formDataBody = generateFormProgressData(currentForm, formValues);
    updateSectionMutation(formDataBody, {
      onError: () => {
        showSnackbar({
          title: t('error_sending_pdf_form'),
          description: t('try_again_later'),
          variant: 'error',
        });
      },
    });
  };

  const lightTheme = useMemo(() => createHuGoTheme({ mode: 'light' }), []);

  const fieldsPerPage: Record<number, SectionComponent[]> | undefined =
    useMemo(() => {
      const components = currentForm?.components;
      return components?.reduce(
        (acc, component) => {
          const page = component.pdfLayout?.page;
          if (page) {
            acc[page] = [...(acc[page] || []), component];
          }
          return acc;
        },
        {} as Record<number, SectionComponent[]>,
      );
    }, [currentForm]);

  return (
    <Stack sx={{ height: 1, minHeight: 0 }}>
      <Stack
        sx={{
          flexDirection: 'row',
          alignItems: 'center',
          justifyContent: 'space-between',
          width: 1,
          p: 2,
          backgroundColor: ({ palette }) =>
            palette.new.background.layout.tertiary,
          borderBottom: ({ palette }) =>
            `1px solid ${palette.new.border.neutral.default}`,
        }}
      >
        <Typography
          variant="globalL"
          fontWeight="fontWeightSemiBold"
        >
          {serviceItem?.name}
        </Typography>
        <IconButton onClick={onCloseForm}>
          <IconX size={24} />
        </IconButton>
      </Stack>
      {/* Main content */}
      <Stack sx={{ flex: 1, minHeight: 0, flexDirection: 'row', width: 1 }}>
        <Stack
          sx={{
            flex: 1,
            minWidth: 0,
            backgroundColor: ({ palette }) =>
              palette.new.background.layout.default,
          }}
        >
          <PdfControls />
          <ThemeProvider theme={lightTheme}>
            <PdfDocumentForm
              pdfFileAsset={pdfFileAsset}
              fieldsPerPage={fieldsPerPage}
            />
          </ThemeProvider>
        </Stack>
        <ExpandableInfoSidebar
          serviceItem={serviceItem!}
          pdfFileAsset={pdfFileAsset}
        />
      </Stack>
      {/* Footer */}
      <Stack
        sx={{
          borderTop: ({ palette }) =>
            `1px solid ${palette.new.border.neutral.default}`,
          width: 1,
          p: 2,
          backgroundColor: ({ palette }) =>
            palette.new.background.layout.tertiary,
        }}
      >
        <Stack
          sx={{
            flexDirection: 'row',
            justifyContent: 'flex-end',
            pr: ['0px', '40px', '160px', '200px'],
            width: 1,
          }}
        >
          <Button
            size="large"
            variant="primary"
            loading={loadingSendForm}
            onClick={handleSubmitForm}
          >
            {t('general:send')}
          </Button>
        </Stack>
      </Stack>
    </Stack>
  );
};

export default PdfFormCompletion;
