const DineroQbFormat = require("./accounting-constants").DineroQbFormat;

const Dinero = require("dinero.js");
const InstanceManager = require("../utils/instanceMgr").default;
const { DiscountNotAlreadyCounted } = InstanceManager({
  imex: require("../job/job-totals"),
  rome: require("../job/job-totals-USA")
});
const logger = require("../utils/logger");

exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes, classes }) {
  const InvoiceLineAdd = [];
  const responsibilityCenters = bodyshop.md_responsibility_centers;

  const invoiceLineHash = {}; //The hash of cost and profit centers based on the center name.

  //Determine if there are MAPA and MASH lines already on the estimate.
  //If there are, don't do anything extra (mitchell estimate)
  //Otherwise, calculate them and add them to the default MAPA and MASH centers.
  let hasMapaLine = false;
  let hasMashLine = false;

  //Create the invoice lines mapping.
  jobs_by_pk.joblines.map((jobline) => {
    if (jobline.db_ref === "936008") {
      //If either of these DB REFs change, they also need to change in job-totals/job-costing calculations.
      hasMapaLine = true;
    }
    if (jobline.db_ref === "936007") {
      hasMashLine = true;
    }

    //Check if the line is a Towing Line and flag as such.
    let isTowingLine = false;
    if (jobline.db_ref === "936001" && jobline.line_desc.includes("Towing")) {
      isTowingLine = true;
    }
    //Parts Lines Mappings.
    if (!isTowingLine && jobline.profitcenter_part) {
      //TODO:AIO This appears to be a net 0 change exept for default quantity as 0 instead of 1 for imex. Need to verify.
      const discountAmount =
        ((jobline.prt_dsmk_m && jobline.prt_dsmk_m !== 0) || (jobline.prt_dsmk_p && jobline.prt_dsmk_p !== 0)) &&
        DiscountNotAlreadyCounted(jobline, jobs_by_pk.joblines)
          ? jobline.prt_dsmk_m
            ? Dinero({ amount: Math.round(jobline.prt_dsmk_m * 100) })
            : Dinero({
                amount: Math.round(jobline.act_price * 100)
              })
                .multiply(jobline.part_qty || 0)
                .percentage(Math.abs(jobline.prt_dsmk_p || 0))
                .multiply(jobline.prt_dsmk_p > 0 ? 1 : -1)
          : Dinero();

      let DineroAmount = Dinero({
        amount: Math.round((jobline.act_price || 0) * 100)
      })
        .multiply(jobline.part_qty || 0)
        .add(discountAmount);

      const account = responsibilityCenters.profits.find(
        (i) => jobline.profitcenter_part.toLowerCase() === i.name.toLowerCase()
      );

      if (!account) {
        logger.log("qbxml-receivables-no-account", "warn", null, jobline.id);
        throw new Error(
          `A matching account does not exist for the part allocation. Center: ${jobline.profitcenter_part}`
        );
      }
      if (qbo) {
        //Do the mapping as per QBO.
        //Determine the Tax code grouping.

        //Going to always assume that we need to apply GST.
        const taxAccountCode = findTaxCode(
          {
            local: false,
            federal: InstanceManager({ imex: true, rome: false }),
            state: checkStateTax(jobline, jobs_by_pk)
          },
          bodyshop.md_responsibility_centers.sales_tax_codes
        );

        const QboTaxId = InstanceManager({
          imex: taxCodes[taxAccountCode],
          rome: CheckQBOUSATaxID({
            jobline: jobline,
            type: "part",
            job: jobs_by_pk
          })
        });
        if (!invoiceLineHash[account.name]) invoiceLineHash[account.name] = {};
        if (!invoiceLineHash[account.name][QboTaxId]) {
          invoiceLineHash[account.name][QboTaxId] = {
            DetailType: "SalesItemLineDetail",
            Amount: DineroAmount,
            SalesItemLineDetail: {
              ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
              ItemRef: {
                value: items[account.accountitem]
              },
              TaxCodeRef: {
                value: QboTaxId
              },
              Qty: 1
            }
          };
        } else {
          invoiceLineHash[account.name][QboTaxId].Amount =
            invoiceLineHash[account.name][QboTaxId].Amount.add(DineroAmount);
        }
      } else {
        if (!invoiceLineHash[account.name]) {
          invoiceLineHash[account.name] = {
            ItemRef: { FullName: account.accountitem },
            Desc: account.accountdesc,
            Quantity: 1, //jobline.part_qty,
            Amount: DineroAmount, //.toFormat(DineroQbFormat),
            SalesTaxCodeRef: InstanceManager({
              imex: {
                FullName: "E"
              },
              rome: {
                FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
              }
            })
          };
        } else {
          invoiceLineHash[account.name].Amount = invoiceLineHash[account.name].Amount.add(DineroAmount);
        }
      }
    }
    //End Parts line mappings.

    //  Labor Lines
    if (jobline.profitcenter_labor && jobline.mod_lb_hrs) {
      const DineroAmount = Dinero({
        amount: Math.round(jobs_by_pk[`rate_${jobline.mod_lbr_ty.toLowerCase()}`] * 100)
      }).multiply(jobline.mod_lb_hrs);
      const account = responsibilityCenters.profits.find(
        (i) => jobline.profitcenter_labor.toLowerCase() === i.name.toLowerCase()
      );

      if (!account) {
        throw new Error(
          `A matching account does not exist for the labor allocation. Center: ${jobline.profitcenter_labor}`
        );
      }
      if (qbo) {
        //Going to always assume that we need to apply GST and PST for labor.
        const taxAccountCode = findTaxCode(
          {
            local: false,
            federal: InstanceManager({ imex: true, rome: false }),
            state: jobs_by_pk.tax_lbr_rt === 0 ? false : true
          },
          bodyshop.md_responsibility_centers.sales_tax_codes
        );

        const QboTaxId = InstanceManager({
          imex: taxCodes[taxAccountCode],
          rome: CheckQBOUSATaxID({ jobline: jobline, type: "labor" })
        });
        if (!invoiceLineHash[account.name]) invoiceLineHash[account.name] = {};
        if (!invoiceLineHash[account.name][QboTaxId]) {
          invoiceLineHash[account.name][QboTaxId] = {
            DetailType: "SalesItemLineDetail",
            Amount: DineroAmount,
            SalesItemLineDetail: {
              ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
              ItemRef: {
                value: items[account.accountitem]
              },
              TaxCodeRef: {
                value: QboTaxId
              },
              Qty: 1
            }
          };
        } else {
          invoiceLineHash[account.name][QboTaxId].Amount =
            invoiceLineHash[account.name][QboTaxId].Amount.add(DineroAmount);
        }
      } else {
        if (!invoiceLineHash[account.name]) {
          invoiceLineHash[account.name] = {
            ItemRef: { FullName: account.accountitem },
            Desc: account.accountdesc,
            Quantity: 1, // jobline.mod_lb_hrs,
            Amount: DineroAmount,
            //Amount: DineroAmount.toFormat(DineroQbFormat),
            SalesTaxCodeRef: InstanceManager({
              imex: {
                FullName: "E"
              },
              rome: {
                FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
              }
            })
          };
        } else {
          invoiceLineHash[account.name].Amount = invoiceLineHash[account.name].Amount.add(DineroAmount);
        }
      }
    }
  });

  if (!hasMapaLine && jobs_by_pk.job_totals.rates.mapa.total.amount > 0) {
    // //console.log("Adding MAPA Line Manually.");
    const mapaAccountName = responsibilityCenters.defaults.profits.MAPA;

    const mapaAccount = responsibilityCenters.profits.find((c) => c.name === mapaAccountName);

    if (mapaAccount) {
      if (qbo) {
        //Add QBO MAPA

        //Going to always assume that we need to apply GST and PST for labor.
        const taxAccountCode = findTaxCode(
          {
            local: false,
            federal: InstanceManager({ imex: true, rome: false }),
            state: jobs_by_pk.tax_paint_mat_rt === 0 ? false : true
          },
          bodyshop.md_responsibility_centers.sales_tax_codes
        );

        const QboTaxId = InstanceManager({
          imex: taxCodes[taxAccountCode],
          rome: CheckQBOUSATaxID({
            // jobline: jobline,
            job: jobs_by_pk,
            type: "materials"
          })
        });
        if (!invoiceLineHash[mapaAccount.name]) invoiceLineHash[mapaAccount.name] = {};
        if (!invoiceLineHash[mapaAccount.name][QboTaxId]) {
          invoiceLineHash[mapaAccount.name][QboTaxId] = {
            DetailType: "SalesItemLineDetail",
            Amount: Dinero(jobs_by_pk.job_totals.rates.mapa.total),
            SalesItemLineDetail: {
              ItemRef: {
                value: items[mapaAccount.accountitem]
              },
              ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
              TaxCodeRef: {
                value: QboTaxId
              },
              Qty: 1
            }
          };
        } else {
          invoiceLineHash[mapaAccount.name][QboTaxId].Amount = invoiceLineHash[mapaAccount.name][QboTaxId].Amount.add(
            Dinero(jobs_by_pk.job_totals.rates.mapa.total)
          );
        }
      } else {
        InvoiceLineAdd.push({
          ItemRef: { FullName: mapaAccount.accountitem },
          Desc: mapaAccount.accountdesc,
          Quantity: 1,
          Amount: Dinero(jobs_by_pk.job_totals.rates.mapa.total).toFormat(DineroQbFormat),
          SalesTaxCodeRef: InstanceManager({
            imex: {
              FullName: "E"
            },
            rome: {
              FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
            }
          })
        });
      }
    } else {
      ////console.log("NO MAPA ACCOUNT FOUND!!");
    }
  }

  if (!hasMashLine && jobs_by_pk.job_totals.rates.mash.total.amount > 0) {
    // //console.log("Adding MASH Line Manually.");

    const mashAccountName = responsibilityCenters.defaults.profits.MASH;

    const mashAccount = responsibilityCenters.profits.find((c) => c.name === mashAccountName);

    if (mashAccount) {
      if (qbo) {
        //Going to always assume that we need to apply GST and PST for labor.
        const taxAccountCode = findTaxCode(
          {
            local: false,
            federal: InstanceManager({ imex: true, rome: false }),
            state: jobs_by_pk.tax_shop_mat_rt === 0 ? false : true
          },
          bodyshop.md_responsibility_centers.sales_tax_codes
        );

        const QboTaxId = InstanceManager({
          imex: taxCodes[taxAccountCode],
          rome: CheckQBOUSATaxID({
            //   jobline: jobline,
            job: jobs_by_pk,
            type: "materials"
          })
        });
        if (!invoiceLineHash[mashAccount.name]) invoiceLineHash[mashAccount.name] = {};
        if (!invoiceLineHash[mashAccount.name][QboTaxId]) {
          invoiceLineHash[mashAccount.name][QboTaxId] = {
            DetailType: "SalesItemLineDetail",
            Amount: Dinero(jobs_by_pk.job_totals.rates.mash.total),
            SalesItemLineDetail: {
              ItemRef: {
                value: items[mashAccount.accountitem]
              },
              ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
              TaxCodeRef: {
                value: QboTaxId
              },
              Qty: 1
            }
          };
        } else {
          invoiceLineHash[mashAccount.name][QboTaxId].Amount = invoiceLineHash[mashAccount.name][QboTaxId].Amount.add(
            Dinero(jobs_by_pk.job_totals.rates.mash.total)
          );
        }
      } else {
        InvoiceLineAdd.push({
          ItemRef: { FullName: mashAccount.accountitem },
          Desc: mashAccount.accountdesc,
          Quantity: 1,
          Amount: Dinero(jobs_by_pk.job_totals.rates.mash.total).toFormat(DineroQbFormat),
          SalesTaxCodeRef: InstanceManager({
            imex: {
              FullName: "E"
            },
            rome: {
              FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
            }
          })
        });
      }
    } else {
      //  //console.log("NO MASH ACCOUNT FOUND!!");
    }
  }

  if (qbo) {
    Object.keys(invoiceLineHash).forEach((key) => {
      Object.keys(invoiceLineHash[key]).forEach((key2) => {
        const account = responsibilityCenters.profits.find((p) => p.name === key);
        InvoiceLineAdd.push({
          ...invoiceLineHash[key][key2],
          ...(account ? { Description: account.accountdesc } : {}),
          Amount: invoiceLineHash[key][key2].Amount.toFormat(DineroQbFormat)
        });
      });
    });
  } else {
    Object.keys(invoiceLineHash).forEach((key) => {
      InvoiceLineAdd.push({
        ...invoiceLineHash[key],
        Amount: invoiceLineHash[key].Amount.toFormat(DineroQbFormat)
      });
    });
  }
  //Convert the hash to an array.

  //Add Towing, storage and adjustment lines.

  ///TODO:AIO Check if this towing check works for imex and not just Rome.
  if (jobs_by_pk.job_totals.additional.towing.amount > 0) {
    if (qbo) {
      //Going to always assume that we need to apply GST and PST for labor.
      const taxAccountCode = findTaxCode(
        {
          local: false,
          federal: InstanceManager({ imex: true, rome: false }),
          state: jobs_by_pk.tax_tow_rt === 0 ? false : true
        },
        bodyshop.md_responsibility_centers.sales_tax_codes
      );
      const account = responsibilityCenters.profits.find(
        (c) => c.name === responsibilityCenters.defaults.profits["TOW"]
      );
      const QboTaxId = InstanceManager({
        imex: taxCodes[taxAccountCode],
        rome: CheckQBOUSATaxID({
          //  jobline: jobline,
          job: jobs_by_pk,
          type: "towing"
        })
      });

      InvoiceLineAdd.push({
        DetailType: "SalesItemLineDetail",
        ///TODO:AIO Check if this towing check works for imex and not just Rome.
        Amount: Dinero(jobs_by_pk.job_totals.additional.towing).toFormat(DineroQbFormat),
        SalesItemLineDetail: {
          ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
          ItemRef: {
            value: items[account.accountitem]
          },
          TaxCodeRef: {
            value: QboTaxId
          },
          Qty: 1
        }
      });
    } else {
      InvoiceLineAdd.push({
        ItemRef: {
          FullName: responsibilityCenters.profits.find((c) => c.name === responsibilityCenters.defaults.profits["TOW"])
            .accountitem
        },
        Desc: "Towing",
        Quantity: 1,
        ///TODO:AIO Check if this towing check works for imex and not just Rome.
        Amount: Dinero(jobs_by_pk.job_totals.additional.towing).toFormat(DineroQbFormat),
        SalesTaxCodeRef: InstanceManager({
          imex: {
            FullName: "E"
          },
          rome: {
            FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
          }
        })
      });
    }
  }
  ///TODO:AIO Check if this storage check works for imex and not just Rome.
  if (jobs_by_pk.job_totals.additional.storage.amount > 0) {
    if (qbo) {
      //Going to always assume that we need to apply GST and PST for labor.
      const taxAccountCode = findTaxCode(
        {
          local: false,
          federal: InstanceManager({ imex: true, rome: false }),
          state: jobs_by_pk.tax_str_rt === 0 ? false : true
        },
        bodyshop.md_responsibility_centers.sales_tax_codes
      );
      const account = responsibilityCenters.profits.find(
        (c) => c.name === responsibilityCenters.defaults.profits["TOW"]
      );
      const QboTaxId = InstanceManager({
        imex: taxCodes[taxAccountCode],
        rome: CheckQBOUSATaxID({
          //    jobline: jobline,
          job: jobs_by_pk,
          type: "storage"
        })
      });
      InvoiceLineAdd.push({
        DetailType: "SalesItemLineDetail",
        ///TODO:AIO Check if this storage check works for imex and not just Rome.

        Amount: Dinero(jobs_by_pk.job_totals.additional.storage.amount).toFormat(DineroQbFormat),
        SalesItemLineDetail: {
          ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
          ItemRef: {
            value: items[account.accountitem]
          },
          TaxCodeRef: {
            value: QboTaxId
          },
          Qty: 1
        }
      });
    } else {
      InvoiceLineAdd.push({
        ItemRef: {
          FullName: responsibilityCenters.profits.find((c) => c.name === responsibilityCenters.defaults.profits["TOW"])
            .accountitem
        },
        Desc: "Storage",
        Quantity: 1,
        ///TODO:AIO Check if this storage check works for imex and not just Rome.

        Amount: Dinero(jobs_by_pk.job_totals.additional.storage.amount).toFormat(DineroQbFormat),
        SalesTaxCodeRef: InstanceManager({
          imex: {
            FullName: "E"
          },
          rome: {
            FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
          }
        })
      });
    }
  }
  if (jobs_by_pk.adjustment_bottom_line && jobs_by_pk.adjustment_bottom_line !== 0) {
    if (qbo) {
      //Going to always assume that we need to apply GST and PST for labor.
      const taxAccountCode = findTaxCode(
        {
          local: false,
          federal: InstanceManager({ imex: true, rome: false }),
          state: jobs_by_pk.tax_lbr_rt === 0 ? false : true
        },
        bodyshop.md_responsibility_centers.sales_tax_codes
      );

      const QboTaxId = InstanceManager({
        imex: taxCodes[taxAccountCode],
        rome: CheckQBOUSATaxID({
          // jobline: jobline,
          type: "adjustment",
          job: jobs_by_pk
        })
      });

      InvoiceLineAdd.push({
        DetailType: "SalesItemLineDetail",
        Amount: Dinero({
          amount: Math.round((jobs_by_pk.adjustment_bottom_line || 0) * 100)
        }).toFormat(DineroQbFormat),
        SalesItemLineDetail: {
          ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
          ItemRef: {
            value: items[responsibilityCenters.refund.accountitem]
          },
          TaxCodeRef: {
            value: QboTaxId
          },
          Qty: 1
        }
      });
    } else {
      InvoiceLineAdd.push({
        ItemRef: {
          FullName: responsibilityCenters.refund.accountitem
        },
        Desc: "Adjustment",
        Quantity: 1,
        Amount: Dinero({
          amount: Math.round((jobs_by_pk.adjustment_bottom_line || 0) * 100)
        }).toFormat(DineroQbFormat),
        SalesTaxCodeRef: InstanceManager({
          imex: {
            FullName: "E"
          },
          rome: {
            FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
          }
        })
      });
    }
  }

  if (jobs_by_pk.job_totals.totals?.ttl_adjustment) {
    // Do not need to check for ImEX or Rome because ImEX uses a different totals calculation that will never set this field.
    if (qbo) {
      const taxAccountCode = findTaxCode(
        {
          local: false,
          federal: InstanceManager({ imex: true, rome: false }),
          state: jobs_by_pk.tax_lbr_rt === 0 ? false : true
        },
        bodyshop.md_responsibility_centers.sales_tax_codes
      );

      const QboTaxId = InstanceManager({
        imex: taxCodes[taxAccountCode],
        rome: CheckQBOUSATaxID({
          // jobline: jobline,
          type: "adjustment",
          job: jobs_by_pk
        })
      });

      InvoiceLineAdd.push({
        DetailType: "SalesItemLineDetail",
        Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_adjustment).toFormat(DineroQbFormat),
        SalesItemLineDetail: {
          ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
          ItemRef: {
            value: items[responsibilityCenters.ttl_adjustment?.accountitem]
          },
          TaxCodeRef: {
            value: QboTaxId
          },
          Qty: 1
        }
      });
    } else {
      InvoiceLineAdd.push({
        ItemRef: {
          FullName: responsibilityCenters.ttl_adjustment?.accountitem
        },
        Desc: "Adjustment",
        Quantity: 1,
        Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_adjustment).toFormat(DineroQbFormat),
        SalesTaxCodeRef: InstanceManager({
          imex: {
            FullName: "E"
          },
          rome: {
            FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
          }
        })
      });
    }
  }

  //Add tax lines
  const job_totals = jobs_by_pk.job_totals;
  const federal_tax = Dinero(job_totals.totals.federal_tax);
  const state_tax = Dinero(job_totals.totals.state_tax);
  const local_tax = Dinero(job_totals.totals.local_tax);

  const RulesetToUse = InstanceManager({ imex: "CANADA", rome: "US" });

  if (RulesetToUse === "CANADA") {
    if (federal_tax.getAmount() > 0) {
      if (qbo) {
        // do qbo
      } else {
        InvoiceLineAdd.push({
          ItemRef: {
            FullName: bodyshop.md_responsibility_centers.taxes.federal.accountitem
          },
          Desc: bodyshop.md_responsibility_centers.taxes.federal.accountdesc,
          Amount: federal_tax.toFormat(DineroQbFormat)
        });
      }
    }

    if (state_tax.getAmount() > 0) {
      if (qbo) {
        // do qbo
      } else {
        InvoiceLineAdd.push({
          ItemRef: {
            FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem
          },
          Desc: bodyshop.md_responsibility_centers.taxes.state.accountdesc,
          Amount: state_tax.toFormat(DineroQbFormat)
        });
      }
    }

    if (local_tax.getAmount() > 0) {
      if (qbo) {
        // do qbo
      } else {
        InvoiceLineAdd.push({
          ItemRef: {
            FullName: bodyshop.md_responsibility_centers.taxes.local.accountitem
          },
          Desc: bodyshop.md_responsibility_centers.taxes.local.accountdesc,
          Amount: local_tax.toFormat(DineroQbFormat)
        });
      }
    }

    //Region Specific
    const { ca_bc_pvrt } = jobs_by_pk;
    if (ca_bc_pvrt) {
      if (qbo) {
        InvoiceLineAdd.push({
          DetailType: "SalesItemLineDetail",
          Amount: Dinero({ amount: (ca_bc_pvrt || 0) * 100 }).toFormat(DineroQbFormat),
          SalesItemLineDetail: {
            ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
            ItemRef: {
              value: items["PVRT"]
            },
            Qty: 1,
            TaxCodeRef: {
              value:
                taxCodes[
                  findTaxCode(
                    {
                      local: false,
                      federal: true,
                      state: false
                    },
                    bodyshop.md_responsibility_centers.sales_tax_codes
                  )
                ]
            }
          }
        });
      } else {
        InvoiceLineAdd.push({
          ItemRef: {
            FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem
          },
          Desc: "PVRT",
          Amount: Dinero({ amount: (ca_bc_pvrt || 0) * 100 }).toFormat(DineroQbFormat)
        });
      }
    }

    //QB USA with GST and PST
    //This was required for the No. 1 Collision Group.
    if (
      bodyshop.accountingconfig &&
      bodyshop.accountingconfig.qbo &&
      bodyshop.accountingconfig.qbo_usa &&
      bodyshop.region_config.includes("CA_")
    ) {
      InvoiceLineAdd.push({
        DetailType: "SalesItemLineDetail",
        Amount: Dinero(jobs_by_pk.job_totals.totals.federal_tax).toFormat(DineroQbFormat),
        SalesItemLineDetail: {
          ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
          ItemRef: {
            value: items[bodyshop.md_responsibility_centers.taxes.federal.accountitem]
          },
          Qty: 1
        }
      });
      InvoiceLineAdd.push({
        DetailType: "SalesItemLineDetail",
        Amount: Dinero(jobs_by_pk.job_totals.totals.state_tax).toFormat(DineroQbFormat),
        SalesItemLineDetail: {
          ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
          ItemRef: {
            value: items[bodyshop.md_responsibility_centers.taxes.state.accountitem]
          },
          Qty: 1
        }
      });
    }
  } else {
    //Handle insurance profile adjustments for Parts
    Object.keys(job_totals.parts.adjustments).forEach((key) => {
      if (qbo) {
        //Going to always assume that we need to apply GST and PST for labor.
        const taxAccountCode = findTaxCode(
          {
            local: false,
            federal: process.env.COUNTRY === "USA" ? false : true,
            state: jobs_by_pk.state_tax_rate === 0 ? false : true
          },
          bodyshop.md_responsibility_centers.sales_tax_codes
        );
        const account = responsibilityCenters.profits.find(
          (c) => c.name === responsibilityCenters.defaults.profits[key]
        );
        const QboTaxId =
          process.env.COUNTRY === "USA"
            ? CheckQBOUSATaxID({
                //    jobline: jobline,
                job: jobs_by_pk,
                type: "storage"
              })
            : taxCodes[taxAccountCode];
        InvoiceLineAdd.push({
          DetailType: "SalesItemLineDetail",
          Amount: Dinero(job_totals.parts.adjustments[key]).toFormat(DineroQbFormat),
          Description: `${account.accountdesc} - Adjustment`,
          SalesItemLineDetail: {
            ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
            ItemRef: {
              value: items[account.accountitem]
            },
            TaxCodeRef: {
              value: QboTaxId
            },
            Qty: 1
          }
        });
      } else {
        InvoiceLineAdd.push({
          ItemRef: {
            FullName: responsibilityCenters.profits.find((c) => c.name === responsibilityCenters.defaults.profits[key])
              .accountitem
          },
          Desc: "Storage",
          Quantity: 1,
          Amount: Dinero(job_totals.parts.adjustments[key]).toFormat(DineroQbFormat),
          SalesTaxCodeRef: {
            FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
          }
        });
      }
    });

    //Handle insurance profile adjustments for Labor and Materials
    Object.keys(job_totals.rates).forEach((key) => {
      if (
        job_totals.rates[key] &&
        job_totals.rates[key].adjustment &&
        Dinero(job_totals.rates[key].adjustment).isZero() === false
      ) {
        if (qbo) {
          //Going to always assume that we need to apply GST and PST for labor.
          const taxAccountCode = findTaxCode(
            {
              local: false,
              federal: process.env.COUNTRY === "USA" ? false : true,
              state: jobs_by_pk.state_tax_rate === 0 ? false : true
            },
            bodyshop.md_responsibility_centers.sales_tax_codes
          );
          const account = responsibilityCenters.profits.find(
            (c) => c.name === responsibilityCenters.defaults.profits[key.toUpperCase()]
          );
          const QboTaxId =
            process.env.COUNTRY === "USA"
              ? CheckQBOUSATaxID({
                  //    jobline: jobline,
                  job: jobs_by_pk,
                  type: "storage"
                })
              : taxCodes[taxAccountCode];
          InvoiceLineAdd.push({
            DetailType: "SalesItemLineDetail",
            Amount: Dinero(job_totals.rates[key].adjustment).toFormat(DineroQbFormat),
            Description: `${account.accountdesc} - Adjustment`,
            SalesItemLineDetail: {
              ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
              ItemRef: {
                value: items[account.accountitem]
              },
              TaxCodeRef: {
                value: QboTaxId
              },
              Qty: 1
            }
          });
        } else {
          InvoiceLineAdd.push({
            ItemRef: {
              FullName: responsibilityCenters.profits.find(
                (c) => c.name === responsibilityCenters.defaults.profits[key.toUpperCase()]
              ).accountitem
            },
            Desc: "Storage",
            Quantity: 1,
            Amount: Dinero(job_totals.rates[key].adjustment).toFormat(DineroQbFormat),
            SalesTaxCodeRef: {
              FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
            }
          });
        }
      }
    });

    const QboTaxId =
      process.env.COUNTRY === "USA"
        ? CheckQBOUSATaxID({
            // jobline: jobline,
            type: "adjustment",
            job: jobs_by_pk
          })
        : taxCodes[taxAccountCode];
    for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
      const taxAmount = Dinero(job_totals.totals.us_sales_tax_breakdown[`ty${tyCounter}Tax`]);
      //console.log(`Tax ${tyCounter}`, taxAmount.toFormat());
      if (taxAmount.getAmount() > 0) {
        if (qbo) {
          InvoiceLineAdd.push({
            DetailType: "SalesItemLineDetail",
            Amount: taxAmount.toFormat(DineroQbFormat),
            SalesItemLineDetail: {
              ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
              ItemRef: {
                value: items[responsibilityCenters.taxes[`tax_ty${tyCounter}`].accountitem]
              },
              TaxCodeRef: {
                value: QboTaxId
              },
              Qty: 1
            }
          });
        } else {
          InvoiceLineAdd.push({
            ItemRef: {
              FullName: bodyshop.md_responsibility_centers.taxes[`tax_ty${tyCounter}`].accountitem
            },
            Desc: bodyshop.md_responsibility_centers.taxes[`tax_ty${tyCounter}`].accountdesc,
            Amount: taxAmount.toFormat(DineroQbFormat)
          });
        }
      }
    }
  }
  if (jobs_by_pk.job_totals.totals.ttl_tax_adjustment) {
    // Do not need to check for ImEX or Rome because ImEX uses a different totals calculation that will never set this field.
    if (qbo) {
      const taxAccountCode = findTaxCode(
        {
          local: false,
          federal: InstanceManager({ imex: true, rome: false }),
          state: jobs_by_pk.tax_lbr_rt === 0 ? false : true
        },
        bodyshop.md_responsibility_centers.sales_tax_codes
      );

      const QboTaxId = InstanceManager({
        imex: taxCodes[taxAccountCode],
        rome: CheckQBOUSATaxID({
          // jobline: jobline,
          type: "adjustment",
          job: jobs_by_pk
        })
      });

      InvoiceLineAdd.push({
        DetailType: "SalesItemLineDetail",
        Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_tax_adjustment).toFormat(DineroQbFormat),
        SalesItemLineDetail: {
          ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
          ItemRef: {
            value: items[responsibilityCenters.ttl_tax_adjustment?.accountitem]
          },
          TaxCodeRef: {
            value: QboTaxId
          },
          Qty: 1
        }
      });
    } else {
      InvoiceLineAdd.push({
        ItemRef: {
          FullName: responsibilityCenters.ttl_tax_adjustment?.accountitem
        },
        Desc: "Tax Adjustment",
        //Quantity: 1,
        Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_tax_adjustment).toFormat(DineroQbFormat),
        // SalesTaxCodeRef: InstanceManager({
        //   imex: {
        //     FullName: "E"
        //   },
        //   rome: {
        //     FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
        //   }
        // })
      });
    }
  }
  if (!qbo && InvoiceLineAdd.length === 0) {
    //Handle the scenario where there is a $0 sale invoice.
    InvoiceLineAdd.push({
      Desc: "No estimate lines."
    });
  }

  //Check if there are multiple payers. If there are, add a deduction line and make sure we create new invoices.

  if (jobs_by_pk.qb_multiple_payers && jobs_by_pk.qb_multiple_payers.length > 0) {
    jobs_by_pk.qb_multiple_payers.forEach((payer) => {
      if (qbo) {
        InvoiceLineAdd.push({
          DetailType: "SalesItemLineDetail",
          Amount: Dinero({
            amount: Math.round((payer.amount || 0) * 100) * -1
          }).toFormat(DineroQbFormat),
          SalesItemLineDetail: {
            ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
            ItemRef: {
              value: items[responsibilityCenters.qb_multiple_payers?.accountitem]
            },
            Qty: 1,
            TaxCodeRef: {
              value:
                taxCodes[
                  findTaxCode(
                    {
                      local: false,
                      federal: false,
                      state: false
                    },
                    bodyshop.md_responsibility_centers.sales_tax_codes
                  )
                ]
            }
          }
        });
      } else {
        InvoiceLineAdd.push({
          ItemRef: {
            FullName: responsibilityCenters.qb_multiple_payers?.accountitem
          },
          Desc: `${payer.name} Liability`,
          Amount: Dinero({
            amount: Math.round((payer.amount || 0) * 100) * -1
          }).toFormat(DineroQbFormat)
        });
      }
    });
  }
  return InvoiceLineAdd;
};

const findTaxCode = ({ local, state, federal }, taxcode) => {
  const t = taxcode.filter((t) => !!t.local === !!local && !!t.state === !!state && !!t.federal === !!federal);
  if (t.length === 1) {
    return t[0].code;
  } else if (t.length > 1) {
    return "Multiple Tax Codes Match";
  } else {
    return "";
  }
};
exports.findTaxCode = findTaxCode;

exports.createMultiQbPayerLines = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes, classes, payer }) {
  const InvoiceLineAdd = [];
  const responsibilityCenters = bodyshop.md_responsibility_centers;

  const invoiceLineHash = {}; //The hash of cost and profit centers based on the center name.

  if (qbo) {
    //Going to always assume that we need to apply GST and PST for labor.
    const taxAccountCode = findTaxCode(
      {
        local: false,
        federal: false,
        state: false
      },
      bodyshop.md_responsibility_centers.sales_tax_codes
    );
    const QboTaxId = taxCodes[taxAccountCode];
    InvoiceLineAdd.push({
      DetailType: "SalesItemLineDetail",
      Amount: Dinero({
        amount: Math.round((payer.amount || 0) * 100)
      }).toFormat(DineroQbFormat),
      SalesItemLineDetail: {
        ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}),
        ItemRef: {
          value: items[responsibilityCenters.qb_multiple_payers?.accountitem]
        },
        TaxCodeRef: {
          value: QboTaxId
        },
        Qty: 1
      }
    });
  } else {
    InvoiceLineAdd.push({
      ItemRef: {
        FullName: responsibilityCenters.qb_multiple_payers?.accountitem
      },
      Desc: `${payer.name} Liability`,
      Quantity: 1,
      Amount: Dinero({
        amount: Math.round((payer.amount || 0) * 100)
      }).toFormat(DineroQbFormat),
      SalesTaxCodeRef: InstanceManager({
        imex: {
          FullName: "E"
        },
        rome: {
          FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON"
        }
      })
    });
  }

  return InvoiceLineAdd;
};

function checkStateTax(jobline, jobs_by_pk) {
  const isPaintOrShopMat = jobline.db_ref === "936008" || jobline.db_ref === "936007";

  if (isPaintOrShopMat) {
    if (jobline.db_ref === "936008") {
      if (jobs_by_pk.tax_paint_mat_rt === 0) {
        return false;
      } else {
        return true;
      }
    }
    if (jobline.db_ref === "936007") {
      if (jobs_by_pk.tax_shop_mat_rt === 0) {
        return false;
      } else {
        return true;
      }
    }
  }

  const isAdditionalCost =
    (jobline.lbr_op === "OP13" ||
      (jobline.lbr_op === "OP14" && jobline.act_price > 0 && jobline.mod_lb_hrs === 0) ||
      (jobline.db_ref && jobline.db_ref.startsWith("9360")) ||
      (jobline.db_ref && jobline.db_ref.startsWith("90051"))) &&
    !isPaintOrShopMat;

  if (!jobline.part_type && isAdditionalCost) {
    if (jobs_by_pk.tax_lbr_rt === 0) {
      return false;
    } else {
      return true;
    }
  }

  if (jobline.tax_part === false) {
    return false;
  } else {
    if (jobline.part_type) {
      if (
        !jobs_by_pk.parts_tax_rates[`${jobline.part_type.toUpperCase()}`] ||
        jobs_by_pk.parts_tax_rates[`${jobline.part_type.toUpperCase()}`].prt_tax_in === false ||
        jobs_by_pk.parts_tax_rates[`${jobline.part_type.toUpperCase()}`].prt_tax_rt === 0
      ) {
        return false;
      } else {
        return true;
      }
    } else {
      if (jobs_by_pk.tax_lbr_rt === 0) {
        return false;
      } else {
        return true;
      }
    }
  }
}

function CheckQBOUSATaxID({ jobline, job, type }) {
  //Replacing this to be all non-taxable items with the refactor of parts tax rates.
  return "NON";
  // if (type === "labor") {
  //   return jobline.lbr_tax ? "TAX" : "NON";
  // } else if (type === "part") {
  //   return jobline.tax_part ? "TAX" : "NON";
  // } else if (type === "materials") {
  //   return job.tax_paint_mat_rt > 0 ? "TAX" : "NON";
  // } else if (type === " towing") {
  //   return true ? "TAX" : "NON";
  // } else if (type === "adjustment") {
  //   return false ? "TAX" : "NON";
  // } else {
  //   throw new Error(`Unknown type to calculate tax id: ${type} `);
  // }
}
