import { useMutation } 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 { logImEXEvent } from "../../firebase/firebase.utils";
import { RECEIVE_PARTS_LINE } from "../../graphql/jobs-lines.queries";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectPartsReceive } from "../../redux/modals/modals.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import PartsReceiveModalComponent from "./parts-receive-modal.component";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop,
  partsReceiveModal: selectPartsReceive
});

const mapDispatchToProps = (dispatch) => ({
  toggleModalVisible: () => dispatch(toggleModalVisible("partsReceive"))
});

export function PartsReceiveModalContainer({ partsReceiveModal, toggleModalVisible, bodyshop }) {
  const { t } = useTranslation();
  const [loading, setLoading] = useState(false);
  const notification = useNotification();

  const { open, context, actions } = partsReceiveModal;
  const { partsorderlines } = context;

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

  const [receivePartsLine] = useMutation(RECEIVE_PARTS_LINE);

  const handleFinish = async (values) => {
    logImEXEvent("parts_order_receive");
    setLoading(true);

    try {
      const submittedLines = values.partsorderlines ?? [];

      // Preserve ids from modal context, merge editable fields from form submission (e.g. location)
      const mergedLines = (partsorderlines ?? []).map((ctxLine, idx) => ({
        ...ctxLine,
        ...submittedLines[idx]
      }));

      // Optional: hard guard to catch the exact failure early with a better message
      const missing = mergedLines
        .map((l, idx) => ({
          idx,
          orderLineId: l?.id,
          jobLineId: l?.joblineid // adjust if your ctx uses job_line_id instead
        }))
        .filter((x) => !x.orderLineId || !x.jobLineId);

      if (missing.length) {
        notification.error({
          title: t("parts_orders.errors.creating"),
          description: `Missing required ids for lines: ${missing
            .map((m) => `#${m.idx + 1} (orderLineId=${m.orderLineId}, jobLineId=${m.jobLineId})`)
            .join(", ")}`
        });
        return;
      }

      const results = await Promise.allSettled(
        mergedLines.map((li) =>
          receivePartsLine({
            variables: {
              lineId: li.joblineid,
              line: {
                location: li.location,
                status: bodyshop.md_order_statuses.default_received || "Received*"
              },
              orderLineId: li.id,
              orderLine: {
                status: bodyshop.md_order_statuses.default_received || "Received*"
              }
            },
            // Ensures GraphQL errors come back on the result when possible (instead of only throwing)
            errorPolicy: "all"
          })
        )
      );

      const errors = [];
      results.forEach((r, idx) => {
        if (r.status === "rejected") {
          errors.push({ idx, message: r.reason?.message ?? String(r.reason) });
          return;
        }
        if (r.value?.errors?.length) {
          errors.push({
            idx,
            message: r.value.errors.map((e) => e.message).join(" | ")
          });
        }
      });

      if (errors.length) {
        errors.forEach((e) =>
          notification.error({
            title: t("parts_orders.errors.creating"),
            description: `Line ${e.idx + 1}: ${e.message}`
          })
        );
        return; // keep modal open so user can retry
      }

      notification.success({ title: t("parts_orders.successes.received") });
      if (refetch) refetch();
      toggleModalVisible();
    } finally {
      setLoading(false);
    }
  };

  const initialValues = {
    partsorderlines: partsorderlines
  };

  useEffect(() => {
    if (open && !!partsorderlines) {
      form.resetFields();
    }
  }, [open, partsorderlines, form]);

  return (
    <Modal
      open={open}
      title={t("parts_orders.labels.receive")}
      onCancel={() => toggleModalVisible()}
      onOk={() => form.submit()}
      okButtonProps={{ loading: loading }}
      destroyOnHidden
      forceRender
      width="50%"
    >
      <Form form={form} layout="vertical" autoComplete="no" onFinish={handleFinish} initialValues={initialValues}>
        <PartsReceiveModalComponent form={form} />
      </Form>
    </Modal>
  );
}

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