// @ts-nocheck
import React, { useMemo } from 'react';
import { Formik, Form } from 'formik';
import { Intent } from '@blueprintjs/core';
import intl from 'react-intl-universal';
import * as R from 'ramda';
import { sumBy, round, isEmpty, omit } from 'lodash';
import classNames from 'classnames';
import { css } from '@emotion/css';
import { useHistory } from 'react-router-dom';

import { CLASSES } from '@/constants/classes';
import {
  CreateJournalSchema,
  EditJournalSchema,
} from './MakeJournalEntries.schema';
import { useMakeJournalFormContext } from './MakeJournalProvider';
import MakeJournalEntriesHeader from './MakeJournalEntriesHeader';
import MakeJournalFormFloatingActions from './MakeJournalFormFloatingActions';
import MakeJournalEntriesField from './MakeJournalEntriesField';
import MakeJournalFormFooter from './MakeJournalFormFooter';
import MakeJournalFormDialogs from './MakeJournalFormDialogs';
import MakeJournalFormTopBar from './MakeJournalFormTopBar';

import withSettings from '@/containers/Settings/withSettings';
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';

import { AppToaster } from '@/components';
import { PageForm } from '@/components/PageForm';
import { compose, orderingLinesIndexes, transactionNumber } from '@/utils';
import {
  transformErrors,
  transformToEditForm,
  defaultManualJournal,
} from './utils';
import { JournalSyncIncrementSettingsToForm } from './components';
import { transformAttachmentsToRequest } from '@/containers/Attachments/utils';

/**
 * Journal entries form.
 */
function MakeJournalEntriesForm({
  // #withSettings
  journalNextNumber,
  journalNumberPrefix,
  journalAutoIncrement,

  // #withCurrentOrganization
  organization: { base_currency },
}) {
  // Journal form context.
  const {
    createJournalMutate,
    editJournalMutate,
    isNewMode,
    manualJournal,
    submitPayload,
  } = useMakeJournalFormContext();

  const history = useHistory();

  // New journal number.
  const journalNumber = transactionNumber(
    journalNumberPrefix,
    journalNextNumber,
  );
  // Form initial values.
  const initialValues = useMemo(
    () => ({
      ...(!isEmpty(manualJournal)
        ? {
            ...transformToEditForm(manualJournal),
          }
        : {
            ...defaultManualJournal,
            // If the auto-increment mode is enabled, take the next journal
            // number from the settings.
            ...(journalAutoIncrement && {
              journal_number: journalNumber,
            }),
            currency_code: base_currency,
          }),
    }),
    [manualJournal, base_currency, journalNumber, journalAutoIncrement],
  );

  // Handle the form submiting.
  const handleSubmit = (values, { setErrors, setSubmitting, resetForm }) => {
    setSubmitting(true);
    const entries = values.entries.filter(
      (entry) => entry.debit || entry.credit,
    );
    // Updated getTotal function using lodash
    const getTotal = (type = 'credit') => {
      return round(
        sumBy(entries, (entry) => parseFloat(entry[type] || 0)),
        2,
      );
    };
    const totalCredit = getTotal('credit');
    const totalDebit = getTotal('debit');

    // Validate the total credit should be equals total debit.
    if (totalCredit !== totalDebit) {
      AppToaster.show({
        message: intl.get('should_total_of_credit_and_debit_be_equal'),
        intent: Intent.DANGER,
      });
      setSubmitting(false);
      return;
    } else if (totalCredit === 0 || totalDebit === 0) {
      AppToaster.show({
        message: intl.get('amount_cannot_be_zero_or_empty'),
        intent: Intent.DANGER,
      });
      setSubmitting(false);
      return;
    }
    const attachments = transformAttachmentsToRequest(values);
    const form = {
      ...omit(values, ['journal_number_manually']),
      ...(values.journal_number_manually && {
        journal_number: values.journal_number,
      }),
      entries: R.compose(orderingLinesIndexes)(entries),
      publish: submitPayload.publish,
      attachments,
    };
    // Handle the request error.
    const handleError = ({
      response: {
        data: { errors },
      },
    }) => {
      transformErrors(errors, { setErrors });
      setSubmitting(false);
    };
    // Handle the request success.
    const handleSuccess = (errors) => {
      AppToaster.show({
        message: intl.get(
          isNewMode
            ? 'the_journal_has_been_created_successfully'
            : 'the_journal_has_been_edited_successfully',
          { number: values.journal_number },
        ),
        intent: Intent.SUCCESS,
      });
      setSubmitting(false);

      if (submitPayload.redirect) {
        history.push('/manual-journals');
      }
      if (submitPayload.resetForm) {
        resetForm();
      }
    };
    if (isNewMode) {
      createJournalMutate(form).then(handleSuccess).catch(handleError);
    } else {
      editJournalMutate([manualJournal.id, form])
        .then(handleSuccess)
        .catch(handleError);
    }
  };

  return (
    <div
      className={classNames(
        CLASSES.PAGE_FORM,
        CLASSES.PAGE_FORM_STRIP_STYLE,
        CLASSES.PAGE_FORM_MAKE_JOURNAL,
      )}
    >
      <Formik
        initialValues={initialValues}
        validationSchema={isNewMode ? CreateJournalSchema : EditJournalSchema}
        onSubmit={handleSubmit}
      >
        <Form
          className={css({
            overflow: 'hidden',
            display: 'flex',
            flexDirection: 'column',
            flex: 1,
          })}
        >
          <PageForm flex={1}>
            <PageForm.Body>
              <MakeJournalFormTopBar />
              <MakeJournalEntriesHeader />
              <MakeJournalEntriesField />
              <MakeJournalFormFooter />
            </PageForm.Body>

            <PageForm.Footer>
              <MakeJournalFormFloatingActions />
            </PageForm.Footer>

            {/* --------- Dialogs --------- */}
            <MakeJournalFormDialogs />

            {/* --------- Effects --------- */}
            <JournalSyncIncrementSettingsToForm />
          </PageForm>
        </Form>
      </Formik>
    </div>
  );
}

export default compose(
  withSettings(({ manualJournalsSettings }) => ({
    journalNextNumber: manualJournalsSettings?.nextNumber,
    journalNumberPrefix: manualJournalsSettings?.numberPrefix,
    journalAutoIncrement: manualJournalsSettings?.autoIncrement,
  })),
  withCurrentOrganization(),
)(MakeJournalEntriesForm);
