import { useMutation } from "@apollo/client";
import { Button, notification } from "antd";
import axios from "axios";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { UPDATE_BILLS } from "../../graphql/bills.queries";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import client from "../../utils/GraphQLClient";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop,
  currentUser: selectCurrentUser
});

function updateBillCache(items) {
  client.cache.modify({
    id: "ROOT_QUERY",
    fields: {
      bills(existingJobs = []) {
        return existingJobs.filter((billRef) => billRef.__ref.includes(items) === false);
      }
    }
  });
}

export function PayableExportButton({
  bodyshop,
  currentUser,
  billId,
  disabled,
  loadingCallback,
  setSelectedBills,
  refetch
}) {
  const { t } = useTranslation();
  const [updateBill] = useMutation(UPDATE_BILLS);
  const [loading, setLoading] = useState(false);
  const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);

  const handleQbxml = async () => {
    logImEXEvent("accounting_export_payable");

    setLoading(true);
    if (!!loadingCallback) loadingCallback(true);

    //Check if it's a QBO Setup.
    let PartnerResponse;
    if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
      PartnerResponse = await axios.post(`/qbo/payables`, {
        bills: [billId],
        elgen: true
      });
    } else {
      //Default is QBD

      let QbXmlResponse;
      try {
        QbXmlResponse = await axios.post(
          "/accounting/qbxml/payables",
          { bills: [billId] },
          {
            headers: {
              Authorization: `Bearer ${await auth.currentUser.getIdToken()}`
            }
          }
        );
      } catch (error) {
        console.log("Error getting QBXML from Server.", error);
        notification["error"]({
          message: t("bills.errors.exporting", {
            error: "Unable to retrieve QBXML. " + JSON.stringify(error.message)
          })
        });
        if (loadingCallback) loadingCallback(false);
        setLoading(false);
        return;
      }

      try {
        PartnerResponse = await axios.post("http://localhost:1337/qb/", QbXmlResponse.data);
      } catch (error) {
        console.log("Error connecting to quickbooks or partner.", error);
        notification["error"]({
          message: t("bills.errors.exporting-partner")
        });
        if (!!loadingCallback) loadingCallback(false);
        setLoading(false);
        return;
      }
    }

    console.log("handleQbxml -> PartnerResponse", PartnerResponse);
    const failedTransactions = PartnerResponse.data.filter((r) => !r.success);
    const successfulTransactions = PartnerResponse.data.filter((r) => r.success);
    if (failedTransactions.length > 0) {
      //Uh oh. At least one was no good.
      failedTransactions.map((ft) =>
        notification["error"]({
          message: t("bills.errors.exporting", {
            error: ft.errorMessage || ""
          })
        })
      );
      if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
        //QBO Logs are handled server side.
        await insertExportLog({
          variables: {
            logs: [
              {
                bodyshopid: bodyshop.id,
                billid: billId,
                successful: false,
                message: JSON.stringify(failedTransactions.map((ft) => ft.errorMessage)),
                useremail: currentUser.email
              }
            ]
          }
        });
      }
    }
    if (successfulTransactions.length > 0) {
      if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
        //QBO Logs are handled server side.
        await insertExportLog({
          variables: {
            logs: [
              {
                bodyshopid: bodyshop.id,
                billid: billId,
                successful: true,
                useremail: currentUser.email
              }
            ]
          }
        });
        const billUpdateResponse = await updateBill({
          variables: {
            billIdList: successfulTransactions.map(
              (st) => st[bodyshop.accountingconfig && bodyshop.accountingconfig.qbo ? "billid" : "id"]
            ),
            bill: {
              exported: true,
              exported_at: new Date()
            }
          }
        });
        if (!!!billUpdateResponse.errors) {
          notification.open({
            type: "success",
            key: "billsuccessexport",
            message: t("bills.successes.exported")
          });
          updateBillCache(billUpdateResponse.data.update_bills.returning.map((bill) => bill.id));
        } else {
          notification["error"]({
            message: t("bills.errors.exporting", {
              error: JSON.stringify(billUpdateResponse.error)
            })
          });
        }
      }
      if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) {
        notification.open({
          type: "success",
          key: "billsuccessexport",
          message: t("bills.successes.exported")
        });
        updateBillCache([
          ...new Set(
            successfulTransactions.map(
              (st) => st[bodyshop.accountingconfig && bodyshop.accountingconfig.qbo ? "billid" : "id"]
            )
          )
        ]);
      }

      if (setSelectedBills) {
        setSelectedBills((selectedBills) => {
          return selectedBills.filter((i) => i !== billId);
        });
      }
    }

    if (!!loadingCallback) loadingCallback(false);
    setLoading(false);
  };

  if (bodyshop.pbs_serialnumber)
    return (
      <Link to="/manage/dmsap" state={{ billids: [billId] }}>
        <Button>{t("jobs.actions.export")}</Button>
      </Link>
    );

  return (
    <Button onClick={handleQbxml} loading={loading} disabled={disabled}>
      {t("jobs.actions.export")}
    </Button>
  );
}

export default connect(mapStateToProps, null)(PayableExportButton);
