import { useMutation } from "@apollo/client";
import { Form, Modal, notification } from "antd";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_NEW_NOTE, UPDATE_NOTE } from "../../graphql/notes.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectNoteUpsert } from "../../redux/modals/modals.selectors";
import { selectCurrentUser } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import NoteUpsertModalComponent from "./note-upsert-modal.component";

const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
  noteUpsertModal: selectNoteUpsert,
});
const mapDispatchToProps = (dispatch) => ({
  toggleModalVisible: () => dispatch(toggleModalVisible("noteUpsert")),
  insertAuditTrail: ({ jobid, operation }) =>
    dispatch(insertAuditTrail({ jobid, operation })),
});

export function NoteUpsertModalContainer({
  currentUser,
  noteUpsertModal,
  toggleModalVisible,
  insertAuditTrail,
}) {
  const { t } = useTranslation();
  const [insertNote] = useMutation(INSERT_NEW_NOTE);
  const [updateNote] = useMutation(UPDATE_NOTE);

  const { visible, context, actions } = noteUpsertModal;
  const { jobId, existingNote } = context;
  const { refetch } = actions;

  const [form] = Form.useForm();

  useEffect(() => {
    //Required to prevent infinite looping.
    if (existingNote && visible) {
      form.setFieldsValue(existingNote);
    } else if (!existingNote && visible) {
      form.resetFields();
    }
  }, [existingNote, form, visible]);

  const handleFinish = async (formValues) => {
    const { relatedros, ...values } = formValues;

    if (existingNote) {
      logImEXEvent("job_note_update");

      updateNote({
        variables: {
          noteId: existingNote.id,
          note: values,
        },
      }).then((r) => {
        notification["success"]({
          message: t("notes.successes.updated"),
        });
        insertAuditTrail({
          jobid: context.jobId,
          operation: AuditTrailMapping.jobnoteupdated(),
        });
      });
      if (refetch) refetch();
      toggleModalVisible();
    } else {
      logImEXEvent("job_note_insert");
      const AdditionalNoteInserts = relatedros
        ? Object.keys(relatedros).filter((key) => relatedros[key])
        : [];

      await insertNote({
        variables: {
          noteInput: [
            { ...values, jobid: jobId, created_by: currentUser.email },
          ],
        },
      });

      if (AdditionalNoteInserts.length > 0) {
        //Insert the others.
        AdditionalNoteInserts.forEach(async (newJobId) => {
          await insertNote({
            variables: {
              noteInput: [
                { ...values, jobid: newJobId, created_by: currentUser.email },
              ],
            },
          });
          insertAuditTrail({
            jobid: newJobId,
            operation: AuditTrailMapping.jobnoteadded(),
          });
        });
      }

      if (refetch) refetch();
      form.resetFields();
      toggleModalVisible();
      notification["success"]({
        message: t("notes.successes.create"),
      });
      insertAuditTrail({
        jobid: context.jobId,
        operation: AuditTrailMapping.jobnoteadded(),
      });
    }
  };

  return (
    <Modal
      title={existingNote ? t("notes.actions.edit") : t("notes.actions.new")}
      visible={visible}
      okText={t("general.actions.save")}
      onOk={() => {
        form.submit();
      }}
      onCancel={() => {
        toggleModalVisible();
      }}
      destroyOnClose
    >
      <Form form={form} onFinish={handleFinish} layout="vertical">
        <NoteUpsertModalComponent form={form} />
      </Form>
    </Modal>
  );
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(NoteUpsertModalContainer);
