import { useMutation, useQuery } from "@apollo/client/react";
import { Form, Modal } from "antd";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { logImEXEvent } from "../../firebase/firebase.utils";
import {
  CANCEL_APPOINTMENT_BY_ID,
  INSERT_APPOINTMENT,
  QUERY_APPOINTMENTS_BY_JOBID
} from "../../graphql/appointments.queries";
import { QUERY_LBR_HRS_BY_PK, UPDATE_JOBS } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { setEmailOptions } from "../../redux/email/email.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectSchedule } from "../../redux/modals/modals.selectors";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { DateTimeFormat } from "../../utils/DateFormatter";
import dayjs from "../../utils/day";
import { TemplateList } from "../../utils/TemplateConstants";
import ScheduleJobModalComponent from "./schedule-job-modal.component";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop,
  scheduleModal: selectSchedule,
  currentUser: selectCurrentUser
});
const mapDispatchToProps = (dispatch) => ({
  toggleModalVisible: () => dispatch(toggleModalVisible("schedule")),
  setEmailOptions: (e) => dispatch(setEmailOptions(e)),
  insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
});

export function ScheduleJobModalContainer({
  scheduleModal,
  bodyshop,
  toggleModalVisible,
  setEmailOptions,
  currentUser,
  insertAuditTrail
}) {
  const notification = useNotification();

  const { open, context, actions } = scheduleModal;
  const { jobId, job, previousEvent } = context;

  const { refetch } = actions;
  const [form] = Form.useForm();

  const { data: lbrHrsData } = useQuery(QUERY_LBR_HRS_BY_PK, {
    variables: { id: job && job.id },
    skip: !job || !job.id,
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only"
  });

  const [loading, setLoading] = useState(false);
  const [cancelAppointment] = useMutation(CANCEL_APPOINTMENT_BY_ID);
  const [insertAppointment] = useMutation(INSERT_APPOINTMENT);
  const [updateJobStatus] = useMutation(UPDATE_JOBS);

  useEffect(() => {
    if (job) form.resetFields();
  }, [job, form]);

  const { t } = useTranslation();

  const existingAppointments = useQuery(QUERY_APPOINTMENTS_BY_JOBID, {
    variables: { jobid: jobId },
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only",
    skip: !open || !jobId
  });

  useEffect(() => {
    if (
      existingAppointments.data &&
      existingAppointments.data.appointments.length > 0 &&
      !existingAppointments.data.appointments[0].canceled
    ) {
      form.setFieldsValue({
        color: existingAppointments.data.appointments[0].color,

        note: existingAppointments.data.appointments[0].note
      });
    }
  }, [existingAppointments.data, form]);

  const handleFinish = async (values) => {
    logImEXEvent("schedule_new_appointment");

    setLoading(true);
    if (previousEvent) {
      const cancelAppt = await cancelAppointment({
        variables: { appid: previousEvent }
      });

      if (cancelAppt.errors) {
        notification.error({
          title: t("appointments.errors.canceling", {
            message: JSON.stringify(cancelAppt.errors)
          })
        });
        return;
      }

      notification.success({
        title: t("appointments.successes.canceled")
      });
    }

    if (existingAppointments.data.appointments.length > 0) {
      await Promise.all(
        existingAppointments.data.appointments.map((app) => {
          return cancelAppointment({
            variables: { appid: app.id }
          });
        })
      );
    }

    const appt = await insertAppointment({
      variables: {
        app: {
          jobid: jobId,
          bodyshopid: bodyshop.id,
          start: dayjs(values.start),
          end: dayjs(values.start).add(bodyshop.appt_length || 60, "minute"),
          color: values.color,
          note: values.note,
          created_by: currentUser.email
        },
        jobId: jobId,
        altTransport: values.alt_transport
      }
    });

    if (!appt.errors) {
      insertAuditTrail({
        jobid: job.id,
        operation: AuditTrailMapping.appointmentinsert(DateTimeFormat(values.start)),
        type: "appointmentinsert"
      });
    }

    if (appt.errors) {
      notification.error({
        title: t("appointments.errors.saving", {
          message: JSON.stringify(appt.errors)
        })
      });
      return;
    }
    notification.success({
      title: t("appointments.successes.created")
    });
    if (jobId) {
      const jobUpdate = await updateJobStatus({
        variables: {
          jobIds: [jobId],
          fields: {
            status: bodyshop.md_ro_statuses.default_scheduled,
            date_scheduled: new Date(),
            scheduled_in: values.start,
            scheduled_completion: values.scheduled_completion,
            lost_sale_reason: null,
            date_lost_sale: null
          }
        }
      });

      if (jobUpdate.errors) {
        notification.error({
          title: t("appointments.errors.saving", {
            message: JSON.stringify(jobUpdate.errors)
          })
        });
        return;
      }
    }
    setLoading(false);
    toggleModalVisible();
    if (values.notifyCustomer) {
      setEmailOptions({
        jobid: jobId,
        messageOptions: {
          to: [values.email],
          replyTo: bodyshop.email,
          subject: TemplateList("appointment").appointment_confirmation.subject
        },
        template: {
          name: TemplateList("appointment").appointment_confirmation.key,
          variables: {
            id: appt.data.insert_appointments.returning[0].id
          }
        }
      });
    }
    if (refetch) refetch();
  };

  return (
    <Modal
      open={open}
      onCancel={() => toggleModalVisible()}
      onOk={() => form.submit()}
      width={"90%"}
      mask={{ closable: false }}
      destroyOnHidden
      okButtonProps={{
        loading: loading
      }}
      closable={false}
    >
      <Form
        form={form}
        layout="vertical"
        onFinish={handleFinish}
        initialValues={{
          notifyCustomer: !!(job && job.ownr_ea),
          email: (job && job.ownr_ea) || "",
          // smartDates: [],
          start: context.scheduled_in,
          scheduled_completion: context.scheduled_completion,
          color: context.color,
          alt_transport: context.alt_transport,
          note: context.note
        }}
      >
        <ScheduleJobModalComponent
          existingAppointments={existingAppointments}
          lbrHrsData={lbrHrsData}
          form={form}
          jobId={jobId}
        />
      </Form>
    </Modal>
  );
}

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