import Icon, { UploadOutlined } from "@ant-design/icons";
import { useApolloClient } from "@apollo/client";
import { MdOpenInNew } from "react-icons/md";
import {
  Alert,
  Divider,
  Form,
  Input,
  Select,
  Space,
  Statistic,
  Switch,
  Upload,
} from "antd";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import FormDatePicker from "../form-date-picker/form-date-picker.component";
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobSearchSelect from "../job-search-select/job-search-select.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
import BillFormLines from "./bill-form.lines.component";
import { CalculateBillTotal } from "./bill-form.totals.utility";
import { useTreatments } from "@splitsoftware/splitio-react";
import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({});

export function BillFormComponent({
  bodyshop,
  disabled,
  form,
  vendorAutoCompleteOptions,
  lineData,
  responsibilityCenters,
  loadLines,
  billEdit,
  disableInvNumber,
  job,
  loadOutstandingReturns,
  loadInventory,
}) {
  const { t } = useTranslation();
  const client = useApolloClient();
  const [discount, setDiscount] = useState(0);
  const { Extended_Bill_Posting } = useTreatments(
    ["Extended_Bill_Posting"],
    {},
    bodyshop.imexshopid
  );

  const handleVendorSelect = (props, opt) => {
    setDiscount(opt.discount);

    opt &&
      !billEdit &&
      loadOutstandingReturns({
        variables: {
          jobId: form.getFieldValue("jobid"),
          vendorId: opt.value,
        },
      });
  };

  useEffect(() => {
    if (job) form.validateFields(["is_credit_memo"]);
  }, [job, form]);

  useEffect(() => {
    const vendorId = form.getFieldValue("vendorid");
    if (vendorId && vendorAutoCompleteOptions) {
      const matchingVendors = vendorAutoCompleteOptions.filter(
        (v) => v.id === vendorId
      );
      if (matchingVendors.length === 1) {
        setDiscount(matchingVendors[0].discount);
      }
    }
    const jobId = form.getFieldValue("jobid");
    if (jobId) {
      loadLines({ variables: { id: jobId } });
      if (form.getFieldValue("is_credit_memo") && vendorId && !billEdit) {
        loadOutstandingReturns({
          variables: {
            jobId: jobId,
            vendorId: vendorId,
          },
        });
      }
    }

    if (vendorId === bodyshop.inhousevendorid && !billEdit) {
      loadInventory();
    }
  }, [
    form,
    billEdit,
    loadOutstandingReturns,
    loadInventory,
    setDiscount,
    vendorAutoCompleteOptions,
    loadLines,
    bodyshop.inhousevendorid,
  ]);

  return (
    <div>
      <FormFieldsChanged form={form} />
      <Form.Item
        style={{ display: "none" }}
        name="isinhouse"
        valuePropName="checked"
      >
        <Switch />
      </Form.Item>
      <LayoutFormRow grow>
        <Form.Item
          name="jobid"
          label={t("bills.fields.ro_number")}
          rules={[
            {
              required: true,
              //message: t("general.validation.required"),
            },
          ]}
        >
          <JobSearchSelect
            disabled={billEdit || disabled}
            convertedOnly
            notExported={false}
            onBlur={() => {
              if (form.getFieldValue("jobid") !== null) {
                loadLines({ variables: { id: form.getFieldValue("jobid") } });
                if (form.getFieldValue("vendorid") !== null) {
                  loadOutstandingReturns({
                    variables: {
                      jobId: form.getFieldValue("jobid"),
                      vendorId: form.getFieldValue("vendorid"),
                    },
                  });
                }
              }
            }}
          />
        </Form.Item>
        <Form.Item
          label={t("bills.fields.vendor")}
          name="vendorid"
          // style={{ display: billEdit ? "none" : null }}
          rules={[
            {
              required: true,
              //message: t("general.validation.required"),
            },
            ({ getFieldValue }) => ({
              validator(rule, value) {
                if (
                  value &&
                  !getFieldValue(["isinhouse"]) &&
                  value === bodyshop.inhousevendorid
                ) {
                  return Promise.reject(t("bills.validation.manualinhouse"));
                }
                return Promise.resolve();
              },
            }),
          ]}
        >
          <VendorSearchSelect
            disabled={disabled}
            options={vendorAutoCompleteOptions}
            onSelect={handleVendorSelect}
          />
        </Form.Item>
      </LayoutFormRow>
      {job &&
        job.ious &&
        job.ious.length > 0 &&
        job.ious.map((iou) => (
          <Alert
            key={iou.id}
            type="warning"
            message={
              <Space>
                {t("bills.labels.iouexists")}
                <Link
                  target="_blank"
                  rel="noopener noreferrer"
                  to={`/manage/jobs/${iou.id}?tab=repairdata`}
                >
                  <Space>
                    {iou.ro_number}
                    <Icon component={MdOpenInNew} />
                  </Space>
                </Link>
              </Space>
            }
          />
        ))}
      <LayoutFormRow>
        <Form.Item
          label={t("bills.fields.invoice_number")}
          name="invoice_number"
          validateTrigger="onBlur"
          hasFeedback
          rules={[
            {
              required: true,
              //message: t("general.validation.required"),
            },
            ({ getFieldValue }) => ({
              async validator(rule, value) {
                const vendorid = getFieldValue("vendorid");
                if (vendorid && value) {
                  const response = await client.query({
                    query: CHECK_BILL_INVOICE_NUMBER,
                    variables: {
                      invoice_number: value,
                      vendorid: vendorid,
                    },
                  });

                  if (response.data.bills_aggregate.aggregate.count === 0) {
                    return Promise.resolve();
                  } else if (
                    response.data.bills_aggregate.nodes.length === 1 &&
                    response.data.bills_aggregate.nodes[0].id ===
                      form.getFieldValue("id")
                  ) {
                    return Promise.resolve();
                  }
                  return Promise.reject(
                    t("bills.validation.unique_invoice_number")
                  );
                } else {
                  return Promise.resolve();
                }
              },
            }),
          ]}
        >
          <Input disabled={disabled || disableInvNumber} />
        </Form.Item>
        <Form.Item
          label={t("bills.fields.date")}
          name="date"
          rules={[
            {
              required: true,
              //message: t("general.validation.required"),
            },
          ]}
        >
          <FormDatePicker disabled={disabled} />
        </Form.Item>
        <Form.Item
          label={t("bills.fields.is_credit_memo")}
          name="is_credit_memo"
          valuePropName="checked"
          rules={[
            ({ getFieldValue }) => ({
              validator(rule, value) {
                if (
                  value === true &&
                  getFieldValue("jobid") &&
                  getFieldValue("vendorid")
                ) {
                  //Removed as this would cause an additional reload when validating the form on submit and clear the values.
                  // loadOutstandingReturns({
                  //   variables: {
                  //     jobId: form.getFieldValue("jobid"),
                  //     vendorId: form.getFieldValue("vendorid"),
                  //   },
                  // });
                }

                if (
                  !bodyshop.bill_allow_post_to_closed &&
                  job &&
                  (job.status === bodyshop.md_ro_statuses.default_invoiced ||
                    job.status === bodyshop.md_ro_statuses.default_exported ||
                    job.status === bodyshop.md_ro_statuses.default_void) &&
                  (value === false || !value)
                ) {
                  return Promise.reject(t("bills.labels.onlycmforinvoiced"));
                }

                return Promise.resolve();
              },
            }),
          ]}
        >
          <Switch />
        </Form.Item>
        <Form.Item
          label={t("bills.fields.total")}
          name="total"
          rules={[
            {
              required: true,
              //message: t("general.validation.required"),
            },
          ]}
        >
          <CurrencyInput min={0} disabled={disabled} />
        </Form.Item>
        {!billEdit && (
          <Form.Item label={t("bills.fields.allpartslocation")} name="location">
            <Select style={{ width: "10rem" }} disabled={disabled} allowClear>
              {bodyshop.md_parts_locations.map((loc, idx) => (
                <Select.Option key={idx} value={loc}>
                  {loc}
                </Select.Option>
              ))}
            </Select>
          </Form.Item>
        )}
      </LayoutFormRow>
      <LayoutFormRow>
        <Form.Item
          span={3}
          label={t("bills.fields.federal_tax_rate")}
          name="federal_tax_rate"
        >
          <CurrencyInput min={0} disabled={disabled} />
        </Form.Item>
        <Form.Item
          span={3}
          label={t("bills.fields.state_tax_rate")}
          name="state_tax_rate"
        >
          <CurrencyInput min={0} disabled={disabled} />
        </Form.Item>
        <Form.Item
          span={3}
          label={t("bills.fields.local_tax_rate")}
          name="local_tax_rate"
        >
          <CurrencyInput min={0} />
        </Form.Item>
        <Form.Item shouldUpdate span={15}>
          {() => {
            const values = form.getFieldsValue([
              "billlines",
              "total",
              "federal_tax_rate",
              "state_tax_rate",
              "local_tax_rate",
            ]);
            let totals;
            if (
              !!values.total &&
              !!values.billlines &&
              values.billlines.length > 0
            )
              totals = CalculateBillTotal(values);
            if (!!totals)
              return (
                <div>
                  <Space wrap>
                    <Statistic
                      title={t("bills.labels.subtotal")}
                      value={totals.subtotal.toFormat()}
                      precision={2}
                    />
                    <Statistic
                      title={t("bills.labels.federal_tax")}
                      value={totals.federalTax.toFormat()}
                      precision={2}
                    />
                    <Statistic
                      title={t("bills.labels.state_tax")}
                      value={totals.stateTax.toFormat()}
                      precision={2}
                    />
                    <Statistic
                      title={t("bills.labels.local_tax")}
                      value={totals.localTax.toFormat()}
                      precision={2}
                    />
                    <Statistic
                      title={t("bills.labels.entered_total")}
                      value={totals.enteredTotal.toFormat()}
                      precision={2}
                    />
                    <Statistic
                      title={t("bills.labels.bill_total")}
                      value={totals.invoiceTotal.toFormat()}
                      precision={2}
                    />
                    <Statistic
                      title={t("bills.labels.discrepancy")}
                      valueStyle={{
                        color:
                          totals.discrepancy.getAmount() === 0
                            ? "green"
                            : "red",
                      }}
                      value={totals.discrepancy.toFormat()}
                      precision={2}
                    />
                  </Space>
                  {form.getFieldValue("is_credit_memo") ? (
                    <AlertComponent
                      type="warning"
                      message={t("bills.labels.enteringcreditmemo")}
                    />
                  ) : null}
                </div>
              );
            return null;
          }}
        </Form.Item>
      </LayoutFormRow>
      <Divider orientation="left">{t("bills.labels.bill_lines")}</Divider>

      {Extended_Bill_Posting.treatment === "on" ? (
        <BillFormLinesExtended
          lineData={lineData}
          discount={discount}
          form={form}
          responsibilityCenters={responsibilityCenters}
          disabled={disabled}
        />
      ) : (
        <BillFormLines
          lineData={lineData}
          discount={discount}
          form={form}
          responsibilityCenters={responsibilityCenters}
          disabled={disabled}
          billEdit={billEdit}
        />
      )}

      <Form.Item
        name="upload"
        label="Upload"
        style={{ display: billEdit ? "none" : null }}
        valuePropName="fileList"
        getValueFromEvent={(e) => {
          if (Array.isArray(e)) {
            return e;
          }
          return e && e.fileList;
        }}
      >
        <Upload.Dragger
          multiple={true}
          name="logo"
          beforeUpload={() => false}
          listType="picture"
        >
          <>
            <p className="ant-upload-drag-icon">
              <UploadOutlined />
            </p>
            <p className="ant-upload-text">
              Click or drag files to this area to upload.
            </p>
          </>
        </Upload.Dragger>
      </Form.Item>
    </div>
  );
}

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