import { useMutation, useQuery } from "@apollo/client/react";
import { Button, Descriptions, InputNumber, Modal, Space } from "antd";
import axios from "axios";
import dayjs from "../../utils/day";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import {
  GET_REFUNDABLE_AMOUNT_BY_JOBID,
  INSERT_PAYMENT_RESPONSE,
  QUERY_PAYMENT_RESPONSE_BY_PAYMENT_ID
} from "../../graphql/payment_response.queries";
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";

const { confirm } = Modal;

const openNotificationWithIcon = (type, t, notification, message) => {
  notification.open({
    type,
    title: t("job_payments.notifications.error.title"),
    description: t("job_payments.notifications.error.description", { message: message || "Unknown error." })
  });
};

const PaymentExpandedRowComponent = ({ record, bodyshop }) => {
  const [refundAmount, setRefundAmount] = useState(0);
  const [insertPayment] = useMutation(INSERT_NEW_PAYMENT);
  const [insertPaymentResponse] = useMutation(INSERT_PAYMENT_RESPONSE);
  const { t } = useTranslation();
  const notification = useNotification();

  const { loading, error, data } = useQuery(QUERY_PAYMENT_RESPONSE_BY_PAYMENT_ID, {
    variables: {
      paymentid: record.id,
      fetchPolicy: "network-only",
      nextFetchPolicy: "network-only"
    }
  });

  const { data: refundable_amount, refetch } = useQuery(GET_REFUNDABLE_AMOUNT_BY_JOBID, {
    variables: {
      jobid: record.jobid
    }
  });

  const insertPayments = async (payment_response, refund_response) => {
    await insertPayment({
      variables: {
        paymentInput: {
          amount: -refund_response?.data?.amount,
          transactionid: payment_response?.response?.receiptelements?.transid,
          payer: record.payer,
          type: "Refund",
          jobid: payment_response.jobid,
          date: dayjs(Date.now())
        }
      },
      update(cache, { data }) {
        cache.modify({
          id: cache.identify({
            id: payment_response.jobid,
            __typename: "jobs"
          }),
          fields: {
            payments(payments) {
              return [...data.insert_payments.returning, ...payments];
            }
          }
        });
      }
    });

    await insertPaymentResponse({
      variables: {
        paymentResponse: {
          amount: -refund_response.data.amount,
          bodyshopid: payment_response.bodyshopid,
          paymentid: payment_response.paymentid,
          jobid: payment_response.jobid,
          declinereason: "Refund",
          ext_paymentid: payment_response.ext_paymentid,
          successful: true,
          response: refund_response.data
        }
      }
    });
  };

  const showConfirm = (payment_response) => {
    confirm({
      title: "Do you want to refund payment?",
      content: "The payment will be refunded. Click OK to confirm and Cancel to dismiss.",
      async onOk() {
        const refundResponse = await axios.post("/intellipay/payment_refund", {
          bodyshop,
          amount: refundAmount,
          paymentid: payment_response.ext_paymentid
        });

        if (refundResponse.data.status < 0) {
          openNotificationWithIcon("error", t, notification, refundResponse.data.message);
          return;
        }

        insertPayments(payment_response, refundResponse);

        // refetch refundable amount
        refetch();
      },
      onCancel() {
        // NO OP
      }
    });
  };

  if (loading) return null;

  if (error) return <p>Error loading data. Please Reload</p>;

  const payment_response = data.payment_response[0];
  const max_refundable_amount = refundable_amount?.payment_response_aggregate.aggregate.sum.amount;

  return (
    <div>
      <Descriptions title={t("job_payments.titles.descriptions")} contentStyle={{ fontWeight: "600" }} column={4}>
        <Descriptions.Item label={t("job_payments.titles.hint")}>
          {payment_response?.response?.methodhint}
        </Descriptions.Item>
        <Descriptions.Item label={t("job_payments.titles.payername")}>
          {payment_response?.response?.nameOnCard ?? ""}
        </Descriptions.Item>
        <Descriptions.Item label={t("job_payments.titles.amount")}>
          <CurrencyFormatter>{record.amount}</CurrencyFormatter>
        </Descriptions.Item>
        <Descriptions.Item label={t("job_payments.titles.dateOfPayment")}>
          {<DateTimeFormatter>{record.created_at}</DateTimeFormatter>}
        </Descriptions.Item>
        <Descriptions.Item label={t("job_payments.titles.transactionid")}>{record.transactionid}</Descriptions.Item>
        <Descriptions.Item label={t("job_payments.titles.paymentid")}>
          {payment_response?.ext_paymentid ?? ""}
        </Descriptions.Item>
        <Descriptions.Item label={t("job_payments.titles.paymenttype")}>{record.type}</Descriptions.Item>
        <Descriptions.Item label={t("job_payments.titles.paymentnum")}>{record.paymentnum}</Descriptions.Item>
        {payment_response && (
          <Descriptions.Item label={t("job_payments.titles.refundamount")}>
            <Space>
              <InputNumber onChange={setRefundAmount} max={max_refundable_amount} min={0} />

              <Button onClick={() => showConfirm(payment_response)}>{t("job_payments.buttons.refundpayment")}</Button>
            </Space>
          </Descriptions.Item>
        )}
      </Descriptions>
    </div>
  );
};

export default PaymentExpandedRowComponent;
