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 dayjs from "../../utils/day";
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 { INSERT_NEW_PAYMENT } from "../../graphql/payments.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 }) =>
    dispatch(insertAuditTrail({ jobid, operation })),
  toggleModalVisible: () => dispatch(toggleModalVisible("cardPayment")),
});

const CardPaymentModalComponent = ({
  bodyshop,
  cardPaymentModal,
  toggleModalVisible,
  insertAuditTrail,
}) => {
  const { context } = 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,
    }
  );

  console.log("🚀 ~ file: card-payment-modal.component..jsx:61 ~ data:", data);
  //Initialize the intellipay window.
  const SetIntellipayCallbackFunctions = () => {
    console.log("*** Set IntelliPay callback functions.");
    window.intellipay.runOnClose(() => {
      //window.intellipay.initialize();
    });

    window.intellipay.runOnApproval(async function (response) {
      console.warn("*** Running On Approval Script ***");
      form.setFieldValue("paymentResponse", response);
      form.submit();
    });

    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(),
        })
      );
    });
  };

  const handleFinish = async (values) => {
    try {
      await insertPayment({
        variables: {
          paymentInput: values.payments.map((payment) => ({
            amount: payment.amount,
            transactionid: (values.paymentResponse.paymentid || "").toString(),
            payer: t("payments.labels.customer"),
            type: values.paymentResponse.cardbrand,
            jobid: payment.jobid,
            date: dayjs(Date.now()),
            payment_responses: {
              data: [
                {
                  amount: payment.amount,
                  bodyshopid: bodyshop.id,

                  jobid: payment.jobid,
                  declinereason: values.paymentResponse.declinereason,
                  ext_paymentid: values.paymentResponse.paymentid.toString(),
                  successful: true,
                  response: values.paymentResponse,
                },
              ],
            },
          })),
        },
        refetchQueries: ["GET_JOB_BY_PK"],
      });
      toggleModalVisible();
    } catch (error) {
      console.error(error);
      notification.open({
        type: "error",
        message: t("payments.errors.inserting", { error: error.message }),
      });
    } finally {
      setLoading(false);
    }
  };

  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,
      });

      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
          onFinish={handleFinish}
          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()
            }
          >
            {() => {
              console.log("Updating the owner info section.");
              //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
              ) {
                console.log("**Calling refetch.");
                refetch({ jobids: payments.map((p) => p.jobid) });
              }
              console.log(
                "Acc info",
                data,
                payments && data && data.jobs.length > 0
                  ? data.jobs.map((j) => j.ro_number).join(", ")
                  : null
              );
              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
                    }
                    hidden
                  />
                  <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
                    }
                    hidden
                  />
                </>
              );
            }}
          </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)}
                    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>

          {/* Lightbox payment response when it is completed */}
          <Form.Item name="paymentResponse" hidden>
            <Input type="hidden" />
          </Form.Item>
        </Form>
      </Spin>
    </Card>
  );
};

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