import { Alert, Button, Card, Tabs, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { SyncOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { resolveRROpCodeFromBodyshop } from "../../utils/dmsUtils.js";

import { selectBodyshop } from "../../redux/user/user.selectors";

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

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

/**
 * Normalize job allocations into a flat list for display / preview building.
 * @param ack
 * @returns {{
 *   center: *,
 *   sale: *,
 *   partsSale: *,
 *   partsTaxableSale: *,
 *   partsNonTaxableSale: *,
 *   laborTaxableSale: *,
 *   laborNonTaxableSale: *,
 *   extrasSale: *,
 *   extrasTaxableSale: *,
 *   extrasNonTaxableSale: *,
 *   cost: *,
 *   profitCenter: *,
 *   costCenter: *
 * }[]|*[]}
 */
function normalizeJobAllocations(ack) {
  if (!ack || !Array.isArray(ack.jobAllocations)) return [];

  return ack.jobAllocations.map((row) => ({
    center: row.center,

    // legacy "sale" (total) if we ever want to show it again
    sale: row.sale || row.totalSale || null,

    // bucketed sales used to build split ROGOG/ROLABOR
    partsSale: row.partsSale || null,
    partsTaxableSale: row.partsTaxableSale || null,
    partsNonTaxableSale: row.partsNonTaxableSale || null,
    laborTaxableSale: row.laborTaxableSale || null,
    laborNonTaxableSale: row.laborNonTaxableSale || null,
    extrasSale: row.extrasSale || null,
    extrasTaxableSale: row.extrasTaxableSale || null,
    extrasNonTaxableSale: row.extrasNonTaxableSale || null,

    cost: row.cost || null,
    profitCenter: row.profitCenter || null,
    costCenter: row.costCenter || null
  }));
}

/**
 * RR-specific DMS Allocations Summary
 * Focused on what we actually send to RR:
 *  - ROGOG (split by taxable / non-taxable segments)
 *  - ROLABOR labor rows with bill hours / rates
 *
 * The heavy lifting (ROGOG/ROLABOR split, cost allocation, tax flags)
 * is now done on the backend via buildRogogFromAllocations/buildRolaborFromRogog.
 * This component just renders the preview from `ack.rogg` / `ack.rolabor`.
 */
export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocationsChange, opCode }) {
  const { t } = useTranslation();
  const [roggPreview, setRoggPreview] = useState(null);
  const [rolaborPreview, setRolaborPreview] = useState(null);
  const [error, setError] = useState(null);
  const socketRef = useRef(socket);

  useEffect(() => {
    socketRef.current = socket;
  }, [socket]);

  // Prefer the user-selected OpCode (from DmsContainer), fall back to config default
  const effectiveOpCode = useMemo(() => opCode || resolveRROpCodeFromBodyshop(bodyshop), [opCode, bodyshop]);

  const fetchAllocations = useCallback(() => {
    if (!socket || !jobId) return;

    try {
      socket.emit("rr-calculate-allocations", { jobId, opCode: effectiveOpCode }, (ack) => {
        if (ack && ack.ok === false) {
          setRoggPreview(null);
          setRolaborPreview(null);
          setError(ack.error || t("dms.labels.allocations_error"));
          if (socketRef.current) {
            socketRef.current.allocationsSummary = [];
            socketRef.current.rrAllocationsRaw = ack;
          }
          if (onAllocationsChange) {
            onAllocationsChange([]);
          }
          return;
        }

        const jobAllocRows = normalizeJobAllocations(ack);

        setRoggPreview(ack?.rogg || null);
        setRolaborPreview(ack?.rolabor || null);
        setError(null);

        if (socketRef.current) {
          socketRef.current.allocationsSummary = jobAllocRows;
          socketRef.current.rrAllocationsRaw = ack;
        }
        if (onAllocationsChange) {
          onAllocationsChange(jobAllocRows);
        }
      });
    } catch {
      setRoggPreview(null);
      setRolaborPreview(null);
      setError(t("dms.labels.allocations_error"));
      if (socketRef.current) {
        socketRef.current.allocationsSummary = [];
      }
      if (onAllocationsChange) {
        onAllocationsChange([]);
      }
    }
  }, [socket, jobId, t, onAllocationsChange, effectiveOpCode]);

  useEffect(() => {
    fetchAllocations();
  }, [fetchAllocations]);

  const segmentLabelMap = {
    partsTaxable: "Parts Taxable",
    partsNonTaxable: "Parts Non-Taxable",
    extrasTaxable: "Extras Taxable",
    extrasNonTaxable: "Extras Non-Taxable",
    laborTaxable: "Labor Taxable",
    laborNonTaxable: "Labor Non-Taxable"
  };

  const roggRows = useMemo(() => {
    if (!roggPreview || !Array.isArray(roggPreview.ops)) return [];

    const rows = [];
    roggPreview.ops.forEach((op) => {
      const rowOpCode = opCode || op.opCode;

      (op.lines || []).forEach((line, idx) => {
        const baseDesc = line.itemDesc;
        const segmentKind = op.segmentKind;
        const segmentCount = op.segmentCount || 0;
        const segmentLabel = segmentLabelMap[segmentKind] || segmentKind;
        const displayDesc = segmentCount > 1 && segmentLabel ? `${baseDesc} (${segmentLabel})` : baseDesc;

        rows.push({
          key: `${op.jobNo}-${idx}`,
          opCode: rowOpCode,
          jobNo: op.jobNo,
          breakOut: line.breakOut,
          itemType: line.itemType,
          itemDesc: displayDesc,
          custQty: line.custQty,
          custPayTypeFlag: line.custPayTypeFlag,
          custTxblNtxblFlag: line.custTxblNtxblFlag,
          custPrice: line.amount?.custPrice,
          dlrCost: line.amount?.dlrCost,
          // segment metadata for visual styling
          segmentKind,
          segmentCount
        });
      });
    });
    return rows;
  }, [roggPreview, opCode, segmentLabelMap]);

  const rolaborRows = useMemo(() => {
    if (!rolaborPreview || !Array.isArray(rolaborPreview.ops)) return [];

    return rolaborPreview.ops
      .filter((op) =>
        [op.bill?.jobTotalHrs, op.bill?.billTime, op.bill?.billRate, op.amount?.custPrice, op.amount?.totalAmt]
          .map((value) => Number.parseFloat(value ?? "0"))
          .some((value) => !Number.isNaN(value) && value !== 0)
      )
      .map((op, idx) => {
        const rowOpCode = opCode || op.opCode;

        return {
          key: `${op.jobNo}-${idx}`,
          opCode: rowOpCode,
          jobNo: op.jobNo,
          custPayTypeFlag: op.custPayTypeFlag,
          custTxblNtxblFlag: op.custTxblNtxblFlag,
          payType: op.bill?.payType,
          jobTotalHrs: op.bill?.jobTotalHrs,
          billTime: op.bill?.billTime,
          billRate: op.bill?.billRate,
          amtType: op.amount?.amtType,
          custPrice: op.amount?.custPrice,
          totalAmt: op.amount?.totalAmt
        };
      });
  }, [rolaborPreview, opCode]);

  // Totals for ROGOG (sum custPrice + dlrCost over all lines)
  const roggTotals = useMemo(() => {
    if (!roggPreview || !Array.isArray(roggPreview.ops)) {
      return { totalCustPrice: "0.00", totalDlrCost: "0.00" };
    }

    let totalCustCents = 0;
    let totalCostCents = 0;

    roggPreview.ops.forEach((op) => {
      (op.lines || []).forEach((line) => {
        const cp = parseFloat(line.amount?.custPrice || "0");
        if (!Number.isNaN(cp)) {
          totalCustCents += Math.round(cp * 100);
        }

        const dc = parseFloat(line.amount?.dlrCost || "0");
        if (!Number.isNaN(dc)) {
          totalCostCents += Math.round(dc * 100);
        }
      });
    });

    return {
      totalCustPrice: (totalCustCents / 100).toFixed(2),
      totalDlrCost: (totalCostCents / 100).toFixed(2)
    };
  }, [roggPreview]);

  const roggColumns = [
    { title: "JobNo", dataIndex: "jobNo", key: "jobNo" },
    { title: "OpCode", dataIndex: "opCode", key: "opCode" },
    { title: "BreakOut", dataIndex: "breakOut", key: "breakOut" },
    { title: "ItemType", dataIndex: "itemType", key: "itemType" },
    { title: "ItemDesc", dataIndex: "itemDesc", key: "itemDesc" },
    { title: "CustQty", dataIndex: "custQty", key: "custQty" },
    { title: "CustTxblFlag", dataIndex: "custTxblNtxblFlag", key: "custTxblNtxblFlag" },
    { title: "CustPrice", dataIndex: "custPrice", key: "custPrice" },
    { title: "DlrCost", dataIndex: "dlrCost", key: "dlrCost" }
  ];

  const rolaborColumns = [
    { title: "JobNo", dataIndex: "jobNo", key: "jobNo" },
    { title: "OpCode", dataIndex: "opCode", key: "opCode" },
    { title: "CustPayType", dataIndex: "custPayTypeFlag", key: "custPayTypeFlag" },
    { title: "CustTxblFlag", dataIndex: "custTxblNtxblFlag", key: "custTxblNtxblFlag" },
    { title: "PayType", dataIndex: "payType", key: "payType" },
    { title: "JobTotalHrs", dataIndex: "jobTotalHrs", key: "jobTotalHrs" },
    { title: "BillTime", dataIndex: "billTime", key: "billTime" },
    { title: "BillRate", dataIndex: "billRate", key: "billRate" },
    { title: "AmtType", dataIndex: "amtType", key: "amtType" },
    { title: "CustPrice", dataIndex: "custPrice", key: "custPrice" },
    { title: "TotalAmt", dataIndex: "totalAmt", key: "totalAmt" }
  ];

  const tabItems = [
    {
      key: "rogog",
      label: "ROGOG Preview",
      children: (
        <>
          <Typography.Paragraph type="secondary" style={{ marginBottom: 8 }}>
            OpCode: <strong>{effectiveOpCode}</strong>. Only centers with RR GOG mapping (rr_gogcode &amp; rr_item_type)
            are included. Totals below reflect exactly what will be sent in ROGOG, with parts, extras, and labor split
            into taxable / non-taxable segments.
          </Typography.Paragraph>

          <ResponsiveTable
            pagination={false}
            columns={roggColumns}
            mobileColumnKeys={["jobNo", "opCode", "breakOut", "itemType"]}
            rowKey="key"
            dataSource={roggRows}
            locale={{ emptyText: "No ROGOG lines would be generated." }}
            scroll={{ x: true }}
            // 👇 visually highlight splits; especially taxable/non-taxable labor segments
            rowClassName={(record) => {
              if (
                record.segmentCount > 1 &&
                (record.segmentKind === "laborTaxable" || record.segmentKind === "laborNonTaxable")
              ) {
                return "rr-allocations-tax-split-row";
              }
              if (record.segmentCount > 1) {
                return "rr-allocations-split-row";
              }
              return "";
            }}
            summary={() => {
              const hasCustTotal = Number(roggTotals.totalCustPrice) !== 0;
              const hasCostTotal = Number(roggTotals.totalDlrCost) !== 0;

              return (
                <ResponsiveTable.Summary.Row>
                  <ResponsiveTable.Summary.Cell index={0}>
                    <Typography.Title level={5}>{t("general.labels.totals")}</Typography.Title>
                  </ResponsiveTable.Summary.Cell>
                  <ResponsiveTable.Summary.Cell index={1} />
                  <ResponsiveTable.Summary.Cell index={2} />
                  <ResponsiveTable.Summary.Cell index={3} />
                  <ResponsiveTable.Summary.Cell index={4} />
                  <ResponsiveTable.Summary.Cell index={5} />
                  <ResponsiveTable.Summary.Cell index={6} />
                  <ResponsiveTable.Summary.Cell index={7}>
                    {hasCustTotal ? roggTotals.totalCustPrice : null}
                  </ResponsiveTable.Summary.Cell>
                  <ResponsiveTable.Summary.Cell index={8}>
                    {hasCostTotal ? roggTotals.totalDlrCost : null}
                  </ResponsiveTable.Summary.Cell>
                </ResponsiveTable.Summary.Row>
              );
            }}
          />
        </>
      )
    },
    {
      key: "rolabor",
      label: "ROLABOR Preview",
      children: (
        <>
          <Typography.Paragraph type="secondary" style={{ marginBottom: 8 }}>
            This mirrors the labor rows RR will receive, including weighted bill hours and rates derived from the
            job&apos;s labor lines.
          </Typography.Paragraph>
          <ResponsiveTable
            pagination={false}
            columns={rolaborColumns}
            mobileColumnKeys={["jobNo", "opCode", "billRate", "custPrice"]}
            rowKey="key"
            dataSource={rolaborRows}
            locale={{ emptyText: "No ROLABOR lines would be generated." }}
            scroll={{ x: true }}
          />
        </>
      )
    }
  ];

  return (
    <Card
      title={title}
      extra={<Button onClick={fetchAllocations} aria-label={t("general.actions.refresh")} icon={<SyncOutlined />} />}
    >
      {bodyshop.pbs_configuration?.disablebillwip && (
        <Alert type="warning" title={t("jobs.labels.dms.disablebillwip")} />
      )}

      {error && <Alert type="error" style={{ marginTop: 8, marginBottom: 8 }} title={error} />}

      <Tabs defaultActiveKey="rogog" items={tabItems} />
    </Card>
  );
}
