import { useMutation, useQuery } from "@apollo/client";
//import moment from "moment";
import { Form, Modal, notification } from "antd";
import moment from "moment-business-days";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
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 { setEmailOptions } from "../../redux/email/email.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectSchedule } from "../../redux/modals/modals.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { TemplateList } from "../../utils/TemplateConstants";
import ScheduleJobModalComponent from "./schedule-job-modal.component";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop,
  scheduleModal: selectSchedule,
});
const mapDispatchToProps = (dispatch) => ({
  toggleModalVisible: () => dispatch(toggleModalVisible("schedule")),
  setEmailOptions: (e) => dispatch(setEmailOptions(e)),
});

export function ScheduleJobModalContainer({
  scheduleModal,
  bodyshop,
  toggleModalVisible,
  setEmailOptions,
}) {
  const { visible, 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: !visible || !!!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"]({
          message: t("appointments.errors.canceling", {
            message: JSON.stringify(cancelAppt.errors),
          }),
        });
        return;
      }

      notification["success"]({
        message: 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: moment(values.start),
          end: moment(values.start).add(bodyshop.appt_length || 60, "minutes"),
          color: values.color,
          note: values.note,
        },
        jobId: jobId,
        altTransport: values.alt_transport,
      },
    });

    if (!!appt.errors) {
      notification["error"]({
        message: t("appointments.errors.saving", {
          message: JSON.stringify(appt.errors),
        }),
      });
      return;
    }
    notification["success"]({
      message: 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,
          },
        },
      });

      if (!!jobUpdate.errors) {
        notification["error"]({
          message: 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
      visible={visible}
      onCancel={() => toggleModalVisible()}
      onOk={() => form.submit()}
      width={"90%"}
      maskClosable={false}
      destroyOnClose
      okButtonProps={{
        loading: loading,
      }}
    >
      <Form
        form={form}
        layout="vertical"
        onFinish={handleFinish}
        initialValues={{
          notifyCustomer: !!(job && job.ownr_ea),
          email: (job && job.ownr_ea) || "",
          start: null,
          // smartDates: [],
          scheduled_completion: null,
          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);
