import { Card, Statistic } from "antd";
import { useTranslation } from "react-i18next";
import PropTypes from "prop-types";
import { defaultKanbanSettings, statisticsItems } from "./settings/defaultKanbanSettings.js";
import Dinero from "dinero.js";

export const StatisticType = {
  HOURS: "hours",
  AMOUNT: "amount",
  JOBS: "jobs",
  TASKS: "tasks"
};

const mergeStatistics = (items, values) => {
  const valuesMap = values.reduce((acc, value) => {
    acc[value.id] = value;
    return acc;
  }, {});

  return items.map((item) => ({
    ...item,
    value: valuesMap[item.id]?.value,
    type: valuesMap[item.id]?.type
  }));
};

const ProductionStatistics = ({ data, cardSettings, reducerData }) => {
  const { t } = useTranslation();

  const calculateTotal = (items, key, subKey) => {
    return items.reduce((acc, item) => acc + (item?.[key]?.aggregate?.sum?.[subKey] ?? 0), 0);
  };

  const calculateTotalAmount = (items, key) => {
    return items.reduce(
      (acc, item) => acc.add(Dinero(item?.[key]?.totals?.subtotal ?? Dinero())),
      Dinero({ amount: 0 })
    );
  };

  const calculateReducerTotalAmount = (lanes, key) => {
    return lanes.reduce(
      (acc, lane) => {
        return acc.add(
          lane.cards.reduce(
            (laneAcc, card) => laneAcc.add(Dinero(card.metadata[key]?.totals?.subtotal ?? Dinero())),
            Dinero({ amount: 0 })
          )
        );
      },
      Dinero({ amount: 0 })
    );
  };

  const calculateReducerTotal = (lanes, key, subKey) => {
    return lanes.reduce((acc, lane) => {
      return (
        acc + lane.cards.reduce((laneAcc, card) => laneAcc + (card.metadata[key]?.aggregate?.sum?.[subKey] || 0), 0)
      );
    }, 0);
  };

  const formatValue = (value, type) => {
    if (type === StatisticType.JOBS) {
      return value.toFixed(0);
    }
    if (type === StatisticType.HOURS) {
      return value.toFixed(2);
    }
    return value;
  };

  const filteredData = cardSettings.excludeSuspended === true ? data.filter((item) => item.suspended !== true) : data;
  const filteredReducerData =
    cardSettings.excludeSuspended === true
      ? {
          ...reducerData,
          lanes: reducerData.lanes.map((lane) => ({
            ...lane,
            cards: lane.cards.filter((card) => card.metadata.suspended !== true)
          }))
        }
      : reducerData;

  const totalHrs = cardSettings.totalHrs
    ? parseFloat(
        (
          calculateTotal(filteredData, "labhrs", "mod_lb_hrs") + calculateTotal(filteredData, "larhrs", "mod_lb_hrs")
        ).toFixed(2)
      )
    : null;

  const totalLAB = cardSettings.totalLAB
    ? parseFloat(calculateTotal(filteredData, "labhrs", "mod_lb_hrs").toFixed(2))
    : null;

  const totalLAR = cardSettings.totalLAR
    ? parseFloat(calculateTotal(filteredData, "larhrs", "mod_lb_hrs").toFixed(2))
    : null;

  const jobsInProduction = cardSettings.jobsInProduction ? filteredData.length : null;

  const totalAmountInProduction = cardSettings.totalAmountInProduction
    ? calculateTotalAmount(filteredData, "job_totals").toFormat("$0,0.00")
    : null;

  const totalAmountOnBoard =
    filteredReducerData && cardSettings.totalAmountOnBoard
      ? calculateReducerTotalAmount(filteredReducerData.lanes, "job_totals").toFormat("$0,0.00")
      : null;

  const totalHrsOnBoard =
    filteredReducerData && cardSettings.totalHrsOnBoard
      ? parseFloat(
          (
            calculateReducerTotal(filteredReducerData.lanes, "labhrs", "mod_lb_hrs") +
            calculateReducerTotal(filteredReducerData.lanes, "larhrs", "mod_lb_hrs")
          ).toFixed(2)
        )
      : null;

  const totalLABOnBoard =
    filteredReducerData && cardSettings.totalLABOnBoard
      ? parseFloat(calculateReducerTotal(filteredReducerData.lanes, "labhrs", "mod_lb_hrs").toFixed(2))
      : null;

  const totalLAROnBoard =
    filteredReducerData && cardSettings.totalLAROnBoard
      ? parseFloat(calculateReducerTotal(filteredReducerData.lanes, "larhrs", "mod_lb_hrs").toFixed(2))
      : null;

  const jobsOnBoard =
    filteredReducerData && cardSettings.jobsOnBoard
      ? filteredReducerData.lanes.reduce((acc, lane) => acc + lane.cards.length, 0)
      : null;

  const tasksInProduction = cardSettings.tasksInProduction
    ? filteredData.reduce((acc, item) => acc + (item.tasks_aggregate?.aggregate?.count || 0), 0)
    : null;

  const tasksOnBoard =
    filteredReducerData && cardSettings.tasksOnBoard
      ? filteredReducerData.lanes.reduce((acc, lane) => {
          return (
            acc +
            lane.cards.reduce((laneAcc, card) => laneAcc + (card.metadata.tasks_aggregate?.aggregate?.count || 0), 0)
          );
        }, 0)
      : null;

  const statistics = mergeStatistics(statisticsItems, [
    { id: 0, value: totalHrs, type: StatisticType.HOURS },
    { id: 1, value: totalAmountInProduction, type: StatisticType.AMOUNT },
    { id: 2, value: totalLAB, type: StatisticType.HOURS },
    { id: 3, value: totalLAR, type: StatisticType.HOURS },
    { id: 4, value: jobsInProduction, type: StatisticType.JOBS },
    { id: 5, value: totalHrsOnBoard, type: StatisticType.HOURS },
    { id: 6, value: totalAmountOnBoard, type: StatisticType.AMOUNT },
    { id: 7, value: totalLABOnBoard, type: StatisticType.HOURS },
    { id: 8, value: totalLAROnBoard, type: StatisticType.HOURS },
    { id: 9, value: jobsOnBoard, type: StatisticType.JOBS },
    { id: 10, value: tasksOnBoard, type: StatisticType.TASKS },
    { id: 11, value: tasksInProduction, type: StatisticType.TASKS }
  ]);

  const statisticsMap = new Map(statistics.map((stat) => [stat.id, stat]));

  const sortedStatistics = (
    cardSettings?.statisticsOrder ? cardSettings.statisticsOrder : defaultKanbanSettings.statisticsOrder
  ).reduce((sorted, orderId) => {
    const value = statisticsMap.get(orderId);
    if (value?.value) {
      sorted.push(value);
    }
    return sorted;
  }, []);

  return (
    <div style={{ display: "flex", gap: "5px", flexWrap: "wrap", marginBottom: "5px" }}>
      {sortedStatistics.map((stat) => (
        <Card styles={{ body: { padding: "8px" } }} key={stat.id}>
          <Statistic
            title={t(`production.statistics.${stat.label}`)}
            value={formatValue(stat.value, stat.type)}
            suffix={
              stat.type === StatisticType.HOURS
                ? t("production.statistics.hours")
                : stat.type === StatisticType.JOBS
                  ? t("production.statistics.jobs")
                  : undefined
            }
          />
        </Card>
      ))}
    </div>
  );
};

ProductionStatistics.propTypes = {
  data: PropTypes.array.isRequired,
  cardSettings: PropTypes.object.isRequired,
  reducerData: PropTypes.object
};

export default ProductionStatistics;
