import { AlertFilled } from "@ant-design/icons";
import { useLazyQuery, useMutation } from "@apollo/client";
import { Button, Divider, Dropdown, Form, Input, Popover, Select, Space } from "antd";
import parsePhoneNumber from "libphonenumber-js";
import queryString from "query-string";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
import { GET_JOB_BY_PK_QUICK_INTAKE, JOB_PRODUCTION_TOGGLE } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateTimeFormatterFunction } from "../../utils/DateFormatter";
import dayjs from "../../utils/day";
import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import DataLabel from "../data-label/data-label.component";
import FormDateTimePickerComponent from "../form-date-time-picker/form-date-time-picker.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.component";
import { HasFeatureAccess } from "./../feature-wrapper/feature-wrapper.component";
import ScheduleAtChange from "./job-at-change.component";
import ScheduleEventColor from "./schedule-event.color.component";
import ScheduleEventNote from "./schedule-event.note.component";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop
});
const mapDispatchToProps = (dispatch) => ({
  setScheduleContext: (context) => dispatch(setModalContext({ context: context, modal: "schedule" })),
  openChatByPhone: (phone) => dispatch(openChatByPhone(phone)),
  setMessage: (text) => dispatch(setMessage(text)),
  insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation }))
});

export function ScheduleEventComponent({
  bodyshop,
  setMessage,
  openChatByPhone,
  event,
  refetch,
  handleCancel,
  setScheduleContext,
  insertAuditTrail
}) {
  const { t } = useTranslation();
  const [open, setOpen] = useState(false);
  const history = useNavigate();
  const searchParams = queryString.parse(useLocation().search);
  const [updateAppointment] = useMutation(UPDATE_APPOINTMENT);
  const [mutationUpdateJob] = useMutation(JOB_PRODUCTION_TOGGLE);
  const [title, setTitle] = useState(event.title);
  const { socket } = useSocket();
  const notification = useNotification();
  const [form] = Form.useForm();
  const [popOverVisible, setPopOverVisible] = useState(false);

  const [getJobDetails] = useLazyQuery(GET_JOB_BY_PK_QUICK_INTAKE, {
    variables: { id: event.job?.id },
    onCompleted: (data) => {
      if (data?.jobs_by_pk) {
        const totalHours =
          (data.jobs_by_pk.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) +
          (data.jobs_by_pk.larhrs?.aggregate?.sum?.mod_lb_hrs || 0);
        form.setFieldsValue({
          actual_in: data.jobs_by_pk.actual_in ? data.jobs_by_pk.actual_in : dayjs(),
          scheduled_completion: data.jobs_by_pk.scheduled_completion
            ? data.jobs_by_pk.scheduled_completion
            : totalHours && bodyshop.ss_configuration.nobusinessdays
              ? dayjs().businessDaysAdd(totalHours / (bodyshop.target_touchtime || 1), "day")
              : dayjs().add(totalHours / (bodyshop.target_touchtime || 1), "day"),
          scheduled_delivery: data.jobs_by_pk.scheduled_delivery
        });
      }
    },

    fetchPolicy: "network-only"
  });

  const blockContent = (
    <Space direction="vertical" wrap>
      <Input
        value={title}
        onChange={(e) => setTitle(e.currentTarget.value)}
        onBlur={async () => {
          await updateAppointment({
            variables: {
              appid: event.id,
              app: {
                title: title
              }
            },
            optimisticResponse: {
              update_appointments: {
                __typename: "appointments_mutation_response",
                returning: [
                  {
                    ...event,
                    title: title,
                    __typename: "appointments"
                  }
                ]
              }
            }
          });
        }}
      />

      <Button onClick={() => handleCancel({ id: event.id })} disabled={event.arrived}>
        {t("appointments.actions.unblock")}
      </Button>
    </Space>
  );

  const handleConvert = async (values) => {
    const res = await mutationUpdateJob({
      variables: {
        jobId: event.job.id,
        job: {
          ...values,
          status: bodyshop.md_ro_statuses.default_arrived,
          inproduction: true
        }
      }
    });

    if (!res.errors) {
      notification["success"]({
        message: t("jobs.successes.converted")
      });
      insertAuditTrail({
        jobid: event.job.id,
        operation: AuditTrailMapping.jobintake(
          res.data.update_jobs.returning[0].status,
          DateTimeFormatterFunction(values.scheduled_completion)
        )
      });
      setPopOverVisible(false);
      refetch();
    }
  };

  const popMenu = (
    <div onClick={(e) => e.stopPropagation()}>
      <Form layout="vertical" form={form} onFinish={handleConvert}>
        <Form.Item
          name={["actual_in"]}
          label={t("jobs.fields.actual_in")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
        >
          <FormDateTimePickerComponent disabled={event.ro_number} />
        </Form.Item>
        <Form.Item
          name={["scheduled_completion"]}
          label={t("jobs.fields.scheduled_completion")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
        >
          <FormDateTimePickerComponent disabled={event.ro_number} />
        </Form.Item>
        <Form.Item name={["scheduled_delivery"]} label={t("jobs.fields.scheduled_delivery")}>
          <FormDateTimePickerComponent disabled={event.ro_number} />
        </Form.Item>

        <Space wrap>
          <Button type="primary" onClick={() => form.submit()}>
            {t("general.actions.save")}
          </Button>
        </Space>
      </Form>
    </div>
  );

  const popoverContent = (
    <div style={{ maxWidth: "40vw" }}>
      {!event.isintake ? (
        <Space>
          <strong>{event.title}</strong>
          <ScheduleEventColor event={event} />
        </Space>
      ) : (
        <Space>
          <strong>
            <OwnerNameDisplay ownerObject={event.job} />
          </strong>
          <span style={{ margin: 4 }}>
            {`${(event.job && event.job.v_model_yr) || ""} ${
              (event.job && event.job.v_make_desc) || ""
            } ${(event.job && event.job.v_model_desc) || ""}`}
          </span>
          <ScheduleEventColor event={event} />
        </Space>
      )}

      {event.job ? (
        <div>
          <DataLabel label={t("jobs.fields.ro_number")}>{(event.job && event.job.ro_number) || ""}</DataLabel>
          <DataLabel label={t("jobs.fields.clm_total")}>
            <CurrencyFormatter>{(event.job && event.job.clm_total) || ""}</CurrencyFormatter>
          </DataLabel>
          <DataLabel hideIfNull label={t("jobs.fields.ins_co_nm")}>
            {(event.job && event.job.ins_co_nm) || ""}
          </DataLabel>
          <DataLabel hideIfNull label={t("jobs.fields.clm_no")}>
            {(event.job && event.job.clm_no) || ""}
          </DataLabel>
          <DataLabel label={t("jobs.fields.ownr_ea")}>{(event.job && event.job.ownr_ea) || ""}</DataLabel>
          <DataLabel label={t("jobs.fields.ownr_ph1")}>
            <ChatOpenButton phone={event.job && event.job.ownr_ph1} jobid={event.job.id} />
          </DataLabel>
          <DataLabel label={t("jobs.fields.ownr_ph2")}>
            <ChatOpenButton phone={event.job && event.job.ownr_ph2} jobid={event.job.id} />
          </DataLabel>
          <DataLabel hideIfNull label={t("jobs.fields.loss_of_use")}>
            {(event.job && event.job.loss_of_use) || ""}
          </DataLabel>
          <DataLabel label={t("jobs.fields.alt_transport")}>
            {(event.job && event.job.alt_transport) || ""}
            <ScheduleAtChange job={event && event.job} />
          </DataLabel>
          <DataLabel label={t("jobs.fields.comment")} valueStyle={{ overflow: "hidden", textOverflow: "ellipsis" }}>
            <ProductionListColumnComment record={event && event.job} />
          </DataLabel>
          <ScheduleEventNote event={event} />
        </div>
      ) : (
        <div>{event.note || ""}</div>
      )}
      <Divider />
      <Space wrap>
        {event.job ? (
          <Link to={`/manage/jobs/${event.job && event.job.id}`}>
            <Button>{t("appointments.actions.viewjob")}</Button>
          </Link>
        ) : null}
        {event.job ? (
          <Button
            onClick={() => {
              history({
                search: queryString.stringify({
                  ...searchParams,
                  selected: event.job.id
                })
              });
            }}
          >
            {t("appointments.actions.preview")}
          </Button>
        ) : null}
        {event.job ? (
          <Dropdown
            menu={{
              items: [
                {
                  key: "email",
                  label: t("general.labels.email"),
                  disabled: event.arrived,
                  onClick: () => {
                    const Template = TemplateList("job").appointment_reminder;
                    GenerateDocument(
                      {
                        name: Template.key,
                        variables: { id: event.job.id }
                      },
                      {
                        to: event.job && event.job.ownr_ea,
                        subject: Template.subject
                      },
                      "e",
                      event.job && event.job.id,
                      notification
                    );
                  }
                },
                {
                  key: "sms",
                  label: t("general.labels.sms"),
                  disabled: event.arrived || !bodyshop.messagingservicesid,
                  onClick: () => {
                    const p = parsePhoneNumber(event.job.ownr_ph1, "CA");
                    if (p && p.isValid()) {
                      openChatByPhone({
                        phone_num: p.formatInternational(),
                        jobid: event.job.id,
                        socket
                      });
                      setMessage(
                        t("appointments.labels.reminder", {
                          shopname: bodyshop.shopname,
                          date: dayjs(event.start).format("MM/DD/YYYY"),
                          time: dayjs(event.start).format("HH:mm a")
                        })
                      );
                      setOpen(false);
                    } else {
                      notification["error"]({
                        message: t("messaging.error.invalidphone")
                      });
                    }
                  }
                }
              ]
            }}
          >
            <Button>{t("appointments.actions.sendreminder")}</Button>
          </Dropdown>
        ) : null}
        {event.arrived ? (
          <Button
            // onClick={() => handleCancel(event.id)}
            disabled={event.arrived}
          >
            {t("appointments.actions.cancel")}
          </Button>
        ) : (
          <Popover
            trigger="click"
            disabled={event.arrived}
            content={
              <Form
                layout="vertical"
                onFinish={({ lost_sale_reason }) => {
                  handleCancel({ id: event.id, lost_sale_reason });
                }}
              >
                <Form.Item
                  name="lost_sale_reason"
                  label={t("jobs.fields.lost_sale_reason")}
                  rules={[
                    {
                      required: true
                      //message: t("general.validation.required"),
                    }
                  ]}
                >
                  <Select
                    options={bodyshop.md_lost_sale_reasons.map((lsr) => ({
                      label: lsr,
                      value: lsr
                    }))}
                  />
                </Form.Item>
                <Button htmlType="submit">{t("appointments.actions.cancel")}</Button>
              </Form>
            }
          >
            <Button
              // onClick={() => handleCancel(event.id)}
              disabled={event.arrived}
            >
              {t("appointments.actions.cancel")}
            </Button>
          </Popover>
        )}

        {event.isintake ? (
          <Button
            disabled={event.arrived}
            onClick={() => {
              setOpen(false);
              setScheduleContext({
                actions: { refetch: refetch },
                context: {
                  jobId: event.job.id,
                  job: event.job,
                  previousEvent: event.id,
                  color: event.color,
                  alt_transport: event.job && event.job.alt_transport,
                  note: event.note
                }
              });
            }}
          >
            {t("appointments.actions.reschedule")}
          </Button>
        ) : (
          <ScheduleManualEvent event={event} />
        )}
        {event.isintake && HasFeatureAccess({ featureName: "checklist", bodyshop }) ? (
          <Link
            to={{
              pathname: `/manage/jobs/${event.job && event.job.id}/intake`,
              search: `?appointmentId=${event.id}`
            }}
          >
            <Button disabled={event.arrived}>{t("appointments.actions.intake")}</Button>
          </Link>
        ) : (
          <Popover //open={open}
            content={popMenu}
            open={popOverVisible}
            onOpenChange={setPopOverVisible}
            onClick={(e) => {
              if (event.job?.id) {
                e.stopPropagation();
                getJobDetails();
              }
            }}
            getPopupContainer={(trigger) => trigger.parentNode}
            trigger="click"
          >
            <Button disabled={event.arrived}>{t("jobs.actions.intake_quick")}</Button>
          </Popover>
        )}
      </Space>
    </div>
  );

  const RegularEvent = event.isintake ? (
    <Space
      wrap
      size="small"
      style={{
        backgroundColor: event.color && event.color.hex ? event.color.hex : event.color
      }}
    >
      {event.note && <AlertFilled className="production-alert" />}
      <strong>{`${event.job.ro_number || t("general.labels.na")}`}</strong>

      <OwnerNameDisplay ownerObject={event.job} />

      {`${(event.job && event.job.v_model_yr) || ""} ${
        (event.job && event.job.v_make_desc) || ""
      } ${(event.job && event.job.v_model_desc) || ""}`}

      {`(${(event.job && event.job.labhrs.aggregate.sum.mod_lb_hrs) || "0"} / ${
        (event.job && event.job.larhrs.aggregate.sum.mod_lb_hrs) || "0"
      })`}

      {event.job && event.job.alt_transport && <div style={{ margin: ".1rem" }}>{event.job.alt_transport}</div>}
      {event?.job?.comment && `C: ${event.job.comment}`}
    </Space>
  ) : (
    <div
      style={{
        height: "100%",
        width: "100%",
        backgroundColor: event.color && event.color.hex ? event.color.hex : event.color
      }}
    >
      <strong>{`${event.title || ""}`}</strong>
    </div>
  );

  return (
    <Popover
      open={open}
      onOpenChange={(vis) => !event.vacation && setOpen(vis)}
      trigger="click"
      content={event.block ? blockContent : popoverContent}
      style={{
        height: "100%",
        width: "100%",

        backgroundColor: event.color && event.color.hex ? event.color.hex : event.color
      }}
    >
      {RegularEvent}
    </Popover>
  );
}

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