import { DeleteFilled } from "@ant-design/icons";
import { useLazyQuery, useMutation } from "@apollo/client";
import { Button, Card, Col, Form, Input, Row, Space, Spin, Statistic, notification } from "antd";
import axios from "axios";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { INSERT_PAYMENT_RESPONSE, QUERY_RO_AND_OWNER_BY_JOB_PKS } from "../../graphql/payment_response.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectCardPayment } from "../../redux/modals/modals.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
import JobSearchSelectComponent from "../job-search-select/job-search-select.component";

const mapStateToProps = createStructuredSelector({
  cardPaymentModal: selectCardPayment,
  bodyshop: selectBodyshop
});

const mapDispatchToProps = (dispatch) => ({
  insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type })),
  toggleModalVisible: () => dispatch(toggleModalVisible("cardPayment"))
});

const CardPaymentModalComponent = ({ bodyshop, cardPaymentModal, toggleModalVisible, insertAuditTrail }) => {
  const { context, actions } = cardPaymentModal;

  const [form] = Form.useForm();

  const [loading, setLoading] = useState(false);
  // const [insertPayment] = useMutation(INSERT_NEW_PAYMENT);
  const [insertPaymentResponse] = useMutation(INSERT_PAYMENT_RESPONSE);
  const { t } = useTranslation();

  const [, { data, refetch, queryLoading }] = useLazyQuery(QUERY_RO_AND_OWNER_BY_JOB_PKS, {
    variables: { jobids: [context.jobid] },
    skip: true
  });

  //Initialize the intellipay window.
  const SetIntellipayCallbackFunctions = () => {
    console.log("*** Set IntelliPay callback functions.");
    window.intellipay.runOnClose(() => {
      //window.intellipay.initialize();
    });

    window.intellipay.runOnApproval(async function (response) {
      //2024-04-25: Nothing is going to happen here anymore. We'll completely rely on the callback.
      //Add a slight delay to allow the refetch to properly get the data.
      setTimeout(() => {
        if (actions && actions.refetch && typeof actions.refetch === "function")
          actions.refetch();
        setLoading(false);
        toggleModalVisible();
      }, 750);
    });

    window.intellipay.runOnNonApproval(async function (response) {
      // Mutate unsuccessful payment

      const { payments } = form.getFieldsValue();
      await insertPaymentResponse({
        variables: {
          paymentResponse: payments.map((payment) => ({
            amount: payment.amount,
            bodyshopid: bodyshop.id,
            jobid: payment.jobid,
            declinereason: response.declinereason,
            ext_paymentid: response.paymentid.toString(),
            successful: false,
            response
          }))
        }
      });

      payments.forEach((payment) =>
        insertAuditTrail({
          jobid: payment.jobid,
          operation: AuditTrailMapping.failedpayment(),
          type: "failedpayment"
        })
      );
    });
  };


  const handleIntelliPayCharge = async () => {
    setLoading(true);
    //Validate
    try {
      await form.validateFields();
    } catch (error) {
      setLoading(false);
      return;
    }

    try {
      const response = await axios.post("/intellipay/lightbox_credentials", {
        bodyshop,
        refresh: !!window.intellipay,
        paymentSplitMeta: form.getFieldsValue(),
      });

      if (window.intellipay) {
        // eslint-disable-next-line no-eval
        eval(response.data);
        SetIntellipayCallbackFunctions();
        window.intellipay.autoOpen();
      } else {
        var rg = document.createRange();
        let node = rg.createContextualFragment(response.data);
        document.documentElement.appendChild(node);
        SetIntellipayCallbackFunctions();
        window.intellipay.isAutoOpen = true;
        window.intellipay.initialize();
      }
    } catch (error) {
      notification.open({
        type: "error",
        message: t("job_payments.notifications.error.openingip")
      });
      setLoading(false);
    }
  };

  return (
    <Card title="Card Payment">
      <Spin spinning={loading}>
        <Form
          form={form}
          layout="vertical"
          initialValues={{
            payments: context.jobid ? [{ jobid: context.jobid }] : []
          }}
        >
          <Form.List name={["payments"]}>
            {(fields, { add, remove, move }) => {
              return (
                <div>
                  {fields.map((field, index) => (
                    <Form.Item key={field.key}>
                      <Row gutter={[16, 16]}>
                        <Col span={16}>
                          <Form.Item
                            key={`${index}jobid`}
                            label={t("jobs.fields.ro_number")}
                            name={[field.name, "jobid"]}
                            rules={[
                              {
                                required: true
                                //message: t("general.validation.required"),
                              }
                            ]}
                          >
                            <JobSearchSelectComponent notExported={false} clm_no />
                          </Form.Item>
                        </Col>
                        <Col span={6}>
                          <Form.Item
                            key={`${index}amount`}
                            label={t("payments.fields.amount")}
                            name={[field.name, "amount"]}
                            rules={[
                              {
                                required: true
                                //message: t("general.validation.required"),
                              }
                            ]}
                          >
                            <CurrencyFormItemComponent />
                          </Form.Item>
                        </Col>
                        <Col span={2}>
                          <DeleteFilled
                            style={{ margin: "1rem" }}
                            onClick={() => {
                              remove(field.name);
                            }}
                          />
                        </Col>
                      </Row>
                    </Form.Item>
                  ))}
                  <Form.Item>
                    <Button
                      type="dashed"
                      onClick={() => {
                        add();
                      }}
                      style={{ width: "100%" }}
                    >
                      {t("general.actions.add")}
                    </Button>
                  </Form.Item>
                </div>
              );
            }}
          </Form.List>

          <Form.Item
            shouldUpdate={(prevValues, curValues) =>
              prevValues.payments?.map((p) => p?.jobid).join() !== curValues.payments?.map((p) => p?.jobid).join()
            }
          >
            {() => {
              //If all of the job ids have been fileld in, then query and update the IP field.
              const { payments } = form.getFieldsValue();
              if (
                payments?.length > 0 &&
                payments?.filter((p) => p?.jobid).length === payments?.length
              ) {
                refetch({ jobids: payments.map((p) => p.jobid) });
              }
              return (
                <>
                  <Input
                    className="ipayfield"
                    data-ipayname="account"
                    type="hidden"
                    value={
                      payments && data && data.jobs.length > 0 ? data.jobs.map((j) => j.ro_number).join(", ") : null
                    }
                  />
                  <Input
                    className="ipayfield"
                    data-ipayname="email"
                    type="hidden"
                    value={
                      payments && data && data.jobs.length > 0 ? data.jobs.filter((j) => j.ownr_ea)[0]?.ownr_ea : null
                    }
                  />
                </>
              );
            }}
          </Form.Item>
          <Form.Item
            shouldUpdate={(prevValues, curValues) =>
              prevValues.payments?.map((p) => p?.amount).join() !== curValues.payments?.map((p) => p?.amount).join()
            }
          >
            {() => {
              const { payments } = form.getFieldsValue();
              const totalAmountToCharge = payments?.reduce((acc, val) => {
                return acc + (val?.amount || 0);
              }, 0);

              return (
                <Space style={{ float: "right" }}>
                  <Statistic title="Amount To Charge" value={totalAmountToCharge} precision={2} />
                  <Input
                    className="ipayfield"
                    data-ipayname="amount"
                    type="hidden"
                    value={totalAmountToCharge?.toFixed(2)}
                  />
                  <Input
                    className="ipayfield"
                    data-ipayname="comment"
                    type="hidden"
                    value={btoa(JSON.stringify(payments))}
                    hidden
                  />
                  <Button
                    type="primary"
                    //  data-ipayname="submit"
                    className="ipayfield"
                    loading={queryLoading || loading}
                    disabled={!(totalAmountToCharge > 0)}
                    onClick={handleIntelliPayCharge}
                  >
                    {t("job_payments.buttons.proceedtopayment")}
                  </Button>
                </Space>
              );
            }}
          </Form.Item>
        </Form>
      </Spin>
    </Card>
  );
};

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