import { Typography } from "antd";
import Dinero from "dinero.js";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import JobCostingPartsTable from "../job-costing-parts-table/job-costing-parts-table.component";
import JobCostingStatistics from "../job-costing-statistics/job-costing-statistics.component";
import JobCostingPie from "./job-costing-modal.pie.component";
import _ from "lodash";
const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
  //setUserLanguage: language => dispatch(setUserLanguage(language))
});

export function JobCostingModalComponent({ bodyshop, job }) {
  const defaultProfits = bodyshop.md_responsibility_centers.defaults.profits;
  const allProfitCenters = _.union(
    bodyshop.md_responsibility_centers.profits.map((p) => p.name),
    bodyshop.md_responsibility_centers.costs.map((p) => p.name)
  );

  // const defaultCosts = bodyshop.md_responsibility_centers.defaults.costs;
  const { t } = useTranslation();
  const jobLineTotalsByProfitCenter =
    job &&
    job.joblines.reduce(
      (acc, val) => {
        const laborProfitCenter = defaultProfits[val.mod_lbr_ty] || "?";

        const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
        const laborAmount = Dinero({
          amount: Math.round((job[rateName] || 0) * 100),
        }).multiply(val.mod_lb_hrs || 0);
        if (!!!acc.labor[laborProfitCenter])
          acc.labor[laborProfitCenter] = Dinero();
        acc.labor[laborProfitCenter] = acc.labor[laborProfitCenter].add(
          laborAmount
        );

        const partsProfitCenter = defaultProfits[val.part_type] || "?";
        if (!!!partsProfitCenter)
          console.log(
            "Unknown cost/profit center mapping for parts.",
            val.part_type
          );
        const partsAmount = Dinero({
          amount: Math.round((val.act_price || 0) * 100),
        }).multiply(val.part_qty || 1);
        if (!!!acc.parts[partsProfitCenter])
          acc.parts[partsProfitCenter] = Dinero();
        acc.parts[partsProfitCenter] = acc.parts[partsProfitCenter].add(
          partsAmount
        );

        return acc;
      },
      { parts: {}, labor: {} }
    );

  const billTotalsByProfitCenter = job.bills.reduce((bill_acc, bill_val) => {
    //At the invoice level.
    bill_val.billlines.map((line_val) => {
      //At the invoice line level.
      //console.log("JobCostingPartsTable -> line_val", line_val);
      if (!!!bill_acc[line_val.cost_center])
        bill_acc[line_val.cost_center] = Dinero();

      bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(
        Dinero({
          amount: Math.round((line_val.actual_cost || 0) * 100),
        })
          .multiply(line_val.quantity)
          .multiply(bill_val.is_credit_memo ? -1 : 1)
      );

      return null;
    });
    return bill_acc;
  }, {});

  const ticketTotalsByProfitCenter = job.timetickets.reduce(
    (ticket_acc, ticket_val) => {
      //At the invoice level.
      if (!!!ticket_acc[ticket_val.cost_center])
        ticket_acc[ticket_val.cost_center] = Dinero();

      ticket_acc[ticket_val.cost_center] = ticket_acc[
        ticket_val.cost_center
      ].add(
        Dinero({
          amount: Math.round((ticket_val.rate || 0) * 100),
        }).multiply(ticket_val.actualhrs || ticket_val.productivehrs || 0)
      );

      return ticket_acc;
    },
    {}
  );

  const summaryData = {
    totalLaborSales: Dinero({ amount: 0 }),
    totalPartsSales: Dinero({ amount: 0 }),
    totalSales: Dinero({ amount: 0 }),
    totalLaborCost: Dinero({ amount: 0 }),
    totalPartsCost: Dinero({ amount: 0 }),
    totalCost: Dinero({ amount: 0 }),
    gpdollars: Dinero({ amount: 0 }),
    gppercent: null,
    gppercentFormatted: null,
  };

  const costCenterData = allProfitCenters.map((key, idx) => {
    const ccVal = key; // defaultProfits[key];
    const sale_labor =
      jobLineTotalsByProfitCenter.labor[ccVal] || Dinero({ amount: 0 });
    const sale_parts =
      jobLineTotalsByProfitCenter.parts[ccVal] || Dinero({ amount: 0 });

    const cost_labor =
      ticketTotalsByProfitCenter[ccVal] || Dinero({ amount: 0 });
    const cost_parts = billTotalsByProfitCenter[ccVal] || Dinero({ amount: 0 });

    const costs = (
      billTotalsByProfitCenter[ccVal] || Dinero({ amount: 0 })
    ).add(ticketTotalsByProfitCenter[ccVal] || Dinero({ amount: 0 }));
    const totalSales = sale_labor.add(sale_parts);
    const gpdollars = totalSales.subtract(costs);
    const gppercent = (
      (gpdollars.getAmount() / totalSales.getAmount()) *
      100
    ).toFixed(2);

    let gppercentFormatted;
    if (isNaN(gppercent)) gppercentFormatted = "0%";
    else if (!isFinite(gppercent)) gppercentFormatted = "- ∞";
    else {
      gppercentFormatted = `${gppercent}%`;
    }
    //Push summary data to avoid extra loop.
    summaryData.totalLaborSales = summaryData.totalLaborSales.add(sale_labor);
    summaryData.totalPartsSales = summaryData.totalPartsSales.add(sale_parts);
    summaryData.totalSales = summaryData.totalSales
      .add(sale_labor)
      .add(sale_parts);
    summaryData.totalLaborCost = summaryData.totalLaborCost.add(cost_labor);
    summaryData.totalPartsCost = summaryData.totalPartsCost.add(cost_parts);
    summaryData.totalCost = summaryData.totalCost.add(costs);

    return {
      id: idx,
      cost_center: ccVal,
      sale_labor: sale_labor && sale_labor.toFormat(),
      sale_parts: sale_parts && sale_parts.toFormat(),
      sales: sale_labor.add(sale_parts).toFormat(),
      sales_dinero: sale_labor.add(sale_parts),
      cost_parts: cost_parts && cost_parts.toFormat(),
      cost_labor: cost_labor && cost_labor.toFormat(),
      costs: cost_parts.add(cost_labor).toFormat(),
      costs_dinero: cost_parts.add(cost_labor),
      gpdollars: gpdollars.toFormat(),
      gppercent: gppercentFormatted,
    };
  });

  //Final summary data massaging.
  summaryData.gpdollars = summaryData.totalSales.subtract(
    summaryData.totalCost
  );
  summaryData.gppercent = (
    (summaryData.gpdollars.getAmount() / summaryData.totalSales.getAmount()) *
    100
  ).toFixed(2);
  if (isNaN(summaryData.gppercent)) summaryData.gppercentFormatted = 0;
  else if (!isFinite(summaryData.gppercent))
    summaryData.gppercentFormatted = "- ∞";
  else {
    summaryData.gppercentFormatted = summaryData.gppercent;
  }

  return (
    <div>
      <JobCostingStatistics job={job} summaryData={summaryData} />
      <JobCostingPartsTable
        job={job}
        data={costCenterData}
        summaryData={summaryData}
      />
      <div className="imex-flex-row">
        <div style={{ flex: 1 }}>
          <Typography.Title level={4}>
            {t("jobs.labels.sales")}
          </Typography.Title>
          <JobCostingPie type="sales" costCenterData={costCenterData} />
        </div>
        <div style={{ flex: 1 }}>
          <Typography.Title level={4}>{t("jobs.labels.cost")}</Typography.Title>
          <JobCostingPie type="cost" costCenterData={costCenterData} />
        </div>
      </div>
    </div>
  );
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(JobCostingModalComponent);
