import { useMutation, useQuery } from "@apollo/client";
import {
  Button,
  Card,
  Form,
  Input,
  InputNumber,
  Row,
  Spin,
  notification,
} from "antd";
import axios from "axios";
import moment from "moment";
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_PK,
} 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 DataLabel from "../data-label/data-label.component";
import JobSearchSelectComponent from "../job-search-select/job-search-select.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.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 amount = Form.useWatch("amount", form);
  const jobid = Form.useWatch("jobid", form);
  const [loading, setLoading] = useState(false);
  const [insertPayment] = useMutation(INSERT_NEW_PAYMENT);
  const [insertPaymentResponse] = useMutation(INSERT_PAYMENT_RESPONSE);
  const { t } = useTranslation();

  const { data, refetch } = useQuery(QUERY_RO_AND_OWNER_BY_JOB_PK, {
    variables: { jobid: context?.jobid ?? "" },
    skip: !context?.jobid,
  });

  //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
      await insertPaymentResponse({
        variables: {
          paymentResponse: {
            amount: response.amount,
            bodyshopid: bodyshop.id,
            jobid: jobid || context.jobid,
            declinereason: response.declinereason,
            ext_paymentid: response.paymentid.toString(),
            successful: false,
            response,
          },
        },
      });
      insertAuditTrail({
        jobid: jobid || context?.jobid,
        operation: AuditTrailMapping.failedpayment(),
      });
    });
  };

  const handleFinish = async (values) => {
    try {
      const paymentResult = await insertPayment({
        variables: {
          paymentInput: {
            amount: values.amount,
            transactionid: (values.paymentResponse.paymentid || "").toString(),
            payer: t("payments.labels.customer"),
            type: values.paymentResponse.cardbrand,
            jobid: values.jobid,
            date: moment(Date.now()),
          },
        },
        refetchQueries: ["GET_JOB_BY_PK"],
        update(cache, { data }) {
          cache.modify({
            id: cache.identify({ id: values.jobid, __typename: "jobs" }),
            fields: {
              payments(cachedPayments) {
                return [...data.insert_payments.returning, ...cachedPayments];
              },
            },
          });
        },
      });

      await insertPaymentResponse({
        variables: {
          paymentResponse: {
            amount: values.amount,
            bodyshopid: bodyshop.id,
            paymentid: paymentResult.data.insert_payments.returning[0].id,
            jobid: values.jobid,
            declinereason: values.paymentResponse.declinereason,
            ext_paymentid: values.paymentResponse.paymentid.toString(),
            successful: true,
            response: values.paymentResponse,
          },
        },
      });
      toggleModalVisible();
    } catch (error) {
      console.error(error);
    } finally {
      setLoading(false);
    }
  };

  const handleIntelliPayCharge = async () => {
    setLoading(true);
    try {
      console.warn("*** Window.Intellipay", !!window.intellipay);

      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}
          initialValues={{ jobid: context?.jobid }}
        >
          <LayoutFormRow grow noDivider>
            <Form.Item
              name="jobid"
              label={t("bills.fields.ro_number")}
              rules={[
                {
                  required: true,
                  // message: t("general.validation.required"),
                },
              ]}
            >
              <JobSearchSelectComponent
                disabled={context?.jobid}
                notExported={false}
                clm_no
                onChange={(e) => {
                  refetch({ jobid: e });
                }}
              />
            </Form.Item>
          </LayoutFormRow>

          {/* Lighbox Input amount needs to be hidden */}
          <Input
            className="ipayfield"
            data-ipayname="amount"
            type="hidden"
            value={amount}
            hidden
          />
          <Input
            className="ipayfield"
            data-ipayname="account"
            type="hidden"
            value={data?.jobs_by_pk.ro_number}
            hidden
          />
          <Input
            className="ipayfield"
            data-ipayname="email"
            type="hidden"
            value={data?.jobs_by_pk.owner.ownr_ea}
            hidden
          />
          {/* Lightbox payment response when it is completed */}
          <Form.Item name="paymentResponse" hidden>
            <Input type="hidden" value={amount} />
          </Form.Item>

          <LayoutFormRow grow>
            <Form.Item
              label="Amount"
              name="amount"
              rules={[
                {
                  required: true,
                  // message: t("general.validation.required"),
                },
              ]}
            >
              <InputNumber />
            </Form.Item>

            <Row justify="space-around">
              <Button
                type="primary"
                //  data-ipayname="submit"
                className="ipayfield"
                disabled={!amount || !jobid}
                onClick={handleIntelliPayCharge}
              >
                {t("job_payments.buttons.proceedtopayment")}
              </Button>
              {context?.balance && (
                <DataLabel
                  valueStyle={{
                    color: context?.balance.getAmount() !== 0 ? "red" : "green",
                  }}
                  label={t("payments.labels.balance")}
                >
                  {context?.balance.toFormat()}
                </DataLabel>
              )}
            </Row>
          </LayoutFormRow>
        </Form>
      </Spin>
    </Card>
  );
};

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