import { Alert, Button, Card, Table, Typography } from "antd";
import { SyncOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import Dinero from "dinero.js";
import { DMS_MAP } from "../../utils/dmsUtils";

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

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

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

/**
 * DMS Allocations Summary component
 * @param mode
 * @param socket
 * @param bodyshop
 * @param jobId
 * @param title
 * @param onAllocationsChange
 * @returns {JSX.Element}
 * @constructor
 */
export function DmsAllocationsSummary({ mode, socket, bodyshop, jobId, title, onAllocationsChange }) {
  const { t } = useTranslation();
  const [allocationsSummary, setAllocationsSummary] = useState([]);

  // Resolve event name by mode (PBS reuses the CDK event per existing behavior)
  const allocationsEvent =
    mode === DMS_MAP.reynolds
      ? "rr-calculate-allocations"
      : mode === DMS_MAP.fortellis
        ? "fortellis-calculate-allocations"
        : /* "cdk" | "pbs" (legacy) */ "cdk-calculate-allocations";

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

    try {
      socket.emit(allocationsEvent, jobId, (ack) => {
        const list = Array.isArray(ack) ? ack : [];
        setAllocationsSummary(list);
        // Preserve side-channel used by the post form for discrepancy checks
        socket.allocationsSummary = list;
        if (onAllocationsChange) onAllocationsChange(list);
      });
    } catch {
      // Best-effort; leave table empty on error
      setAllocationsSummary([]);
      if (socket) {
        socket.allocationsSummary = [];
      }
      if (onAllocationsChange) {
        onAllocationsChange([]);
      }
    }
  }, [socket, jobId, mode, allocationsEvent]);

  // Initial + whenever mode/socket/jobId changes
  useEffect(() => {
    fetchAllocations();
  }, [fetchAllocations]);

  const columns = [
    { title: t("jobs.fields.dms.center"), dataIndex: "center", key: "center" },
    {
      title: t("jobs.fields.dms.sale"),
      dataIndex: "sale",
      key: "sale",
      render: (_text, record) => Dinero(record.sale).toFormat()
    },
    {
      title: t("jobs.fields.dms.cost"),
      dataIndex: "cost",
      key: "cost",
      render: (_text, record) => Dinero(record.cost).toFormat()
    },
    {
      title: t("jobs.fields.dms.sale_dms_acctnumber"),
      dataIndex: "sale_dms_acctnumber",
      key: "sale_dms_acctnumber",
      render: (_text, record) => record.profitCenter?.dms_acctnumber
    },
    {
      title: t("jobs.fields.dms.cost_dms_acctnumber"),
      dataIndex: "cost_dms_acctnumber",
      key: "cost_dms_acctnumber",
      render: (_text, record) => record.costCenter?.dms_acctnumber
    },
    {
      title: t("jobs.fields.dms.dms_wip_acctnumber"),
      dataIndex: "dms_wip_acctnumber",
      key: "dms_wip_acctnumber",
      render: (_text, record) => record.costCenter?.dms_wip_acctnumber
    }
  ];

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

      <Table
        pagination={{ position: "top", defaultPageSize: pageLimit }}
        columns={columns}
        rowKey="center"
        dataSource={allocationsSummary}
        locale={{ emptyText: t("dms.labels.refreshallocations") }}
        scroll={{ x: true }}
        summary={() => {
          const totals = allocationsSummary?.reduce(
            (acc, val) => ({
              totalSale: acc.totalSale.add(Dinero(val.sale)),
              totalCost: acc.totalCost.add(Dinero(val.cost))
            }),
            { totalSale: Dinero(), totalCost: Dinero() }
          ) || { totalSale: Dinero(), totalCost: Dinero() };

          const hasNonZeroSaleTotal = totals.totalSale.getAmount() !== 0;

          return (
            <Table.Summary.Row>
              <Table.Summary.Cell>
                <Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title>
              </Table.Summary.Cell>
              <Table.Summary.Cell>{hasNonZeroSaleTotal ? totals.totalSale.toFormat() : null}</Table.Summary.Cell>
              <Table.Summary.Cell />
              <Table.Summary.Cell />
              <Table.Summary.Cell />
            </Table.Summary.Row>
          );
        }}
      />
    </Card>
  );
}
