"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
  Alert,
  Box,
  Button,
  CircularProgress,
  Grid,
  MenuItem,
  Paper,
  Stack,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableRow,
  TextField,
  Typography,
} from "@mui/material";
import type { ApexOptions } from "apexcharts";
import dayjs from "dayjs";
import { useTranslation } from "react-i18next";
import * as XLSX from "xlsx-js-style";
import {
  CompletedJobOrderPickOrderDashboardRecord,
  fetchPlasticBoxCartonQtyDashboard,
} from "@/app/api/jo/actions";
import SafeApexCharts from "@/components/charts/SafeApexCharts";

/** Day.js has no typed `dayjs.invalid()` factory; Invalid Date parses to an invalid Dayjs instance. */
const DAYJS_INVALID = dayjs(new Date(Number.NaN));

type FloorFilter = "all" | "2/F" | "3/F" | "4/F";

type DailySummaryRow = {
  date: string;
  floor2F: number;
  floor3F: number;
  floor4F: number;
  total: number;
};

const hasPlasticQty = (record: CompletedJobOrderPickOrderDashboardRecord): boolean =>
  record.plasticBoxCartonQty2f != null ||
  record.plasticBoxCartonQty3f != null ||
  record.plasticBoxCartonQty4f != null;

/** Backend may return LocalDateTime as [y,m,d,h,mi,s] — align with completeJobOrderRecord.toDateYMD */
const parseRecordDate = (record: CompletedJobOrderPickOrderDashboardRecord): dayjs.Dayjs => {
  if (record.statDate) {
    const d = dayjs(record.statDate, "YYYY-MM-DD", true);
    if (d.isValid()) return d;
  }

  const raw = record.completedDate ?? record.planStart;
  if (!raw) return DAYJS_INVALID;

  if (Array.isArray(raw)) {
    const [year, month, day] = raw;
    if (year != null && month != null && day != null) {
      return dayjs(new Date(Number(year), Number(month) - 1, Number(day)));
    }
    return DAYJS_INVALID;
  }

  if (typeof raw === "string") {
    const strict = dayjs(raw, ["YYYY-MM-DD", "YYYY-MM-DDTHH:mm:ss", "YYYY-MM-DDTHH:mm:ss.SSS"], true);
    return strict.isValid() ? strict : dayjs(raw);
  }

  return dayjs(raw);
};

const addRecordQty = (
  current: DailySummaryRow,
  record: CompletedJobOrderPickOrderDashboardRecord,
  selectedFloor: FloorFilter,
) => {
  const q2 = Number(record.plasticBoxCartonQty2f ?? 0);
  const q3 = Number(record.plasticBoxCartonQty3f ?? 0);
  const q4 = Number(record.plasticBoxCartonQty4f ?? 0);

  if (selectedFloor === "all" || selectedFloor === "2/F") {
    current.floor2F += q2;
  }
  if (selectedFloor === "all" || selectedFloor === "3/F") {
    current.floor3F += q3;
  }
  if (selectedFloor === "all" || selectedFloor === "4/F") {
    current.floor4F += q4;
  }

  if (selectedFloor === "all") {
    current.total += q2 + q3 + q4;
  } else if (selectedFloor === "2/F") {
    current.total += q2;
  } else if (selectedFloor === "3/F") {
    current.total += q3;
  } else {
    current.total += q4;
  }
};

const PlasticBoxCartonDashboardTab: React.FC = () => {
  const { t } = useTranslation("jo");
  const exportInFlightRef = useRef(false);
  const [floor, setFloor] = useState<FloorFilter>("all");
  const [date, setDate] = useState<string>(dayjs().format("YYYY-MM-DD"));
  const [loading, setLoading] = useState(false);
  const [isExporting, setIsExporting] = useState(false);
  const [error, setError] = useState<string>("");
  const [records, setRecords] = useState<CompletedJobOrderPickOrderDashboardRecord[]>([]);

  const loadData = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const day = date && dayjs(date).isValid() ? dayjs(date).format("YYYY-MM-DD") : dayjs().format("YYYY-MM-DD");
      const data = await fetchPlasticBoxCartonQtyDashboard(day, day);
      setRecords(data);
    } catch (err) {
      console.error("Failed to load plastic box carton dashboard data", err);
      setError(t("Failed to load plastic box carton qty dashboard"));
      setRecords([]);
    } finally {
      setLoading(false);
    }
  }, [date, t]);

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

  const rows = useMemo<DailySummaryRow[]>(() => {
    const summary = new Map<string, DailySummaryRow>();

    records.forEach((record) => {
      const dayObj = parseRecordDate(record);
      const day = dayObj.isValid() ? dayObj.format("YYYY-MM-DD") : "-";

      const current = summary.get(day) ?? {
        date: day,
        floor2F: 0,
        floor3F: 0,
        floor4F: 0,
        total: 0,
      };

      addRecordQty(current, record, floor);
      summary.set(day, current);
    });

    return Array.from(summary.values()).sort((a, b) => b.date.localeCompare(a.date));
  }, [records, floor]);

  const chartOptions = useMemo<ApexOptions>(
    () => ({
      chart: {
        type: "bar",
        toolbar: { show: false },
      },
      colors: ["#1976d2", "#9c27b0", "#ff9800", "#2e7d32"],
      dataLabels: { enabled: false },
      stroke: { show: true, width: 1, colors: ["transparent"] },
      plotOptions: {
        bar: {
          horizontal: false,
          borderRadius: 3,
          columnWidth: "55%",
        },
      },
      xaxis: {
        categories: rows.map((row) => row.date),
        title: { text: t("Date") },
      },
      yaxis: {
        title: { text: t("Plastic box carton Qty") },
        labels: {
          formatter: (val) => Number(val || 0).toLocaleString("zh-HK"),
        },
      },
      tooltip: {
        y: {
          formatter: (val) =>
            `${Number(val || 0).toLocaleString("zh-HK")} ${t("Plastic box carton Qty")}`,
        },
      },
      legend: {
        position: "top",
      },
      noData: {
        text: t("No chart data"),
      },
    }),
    [rows, t],
  );

  const chartSeries = useMemo(
    () => [
      { name: "2/F", data: rows.map((row) => row.floor2F) },
      { name: "3/F", data: rows.map((row) => row.floor3F) },
      { name: "4/F", data: rows.map((row) => row.floor4F) },
      { name: t("Total plastic box carton qty"), data: rows.map((row) => row.total) },
    ],
    [rows, t],
  );

  const summary = useMemo(() => {
    return rows.reduce(
      (acc, row) => {
        acc.floor2F += row.floor2F;
        acc.floor3F += row.floor3F;
        acc.floor4F += row.floor4F;
        acc.total += row.total;
        return acc;
      },
      { floor2F: 0, floor3F: 0, floor4F: 0, total: 0 },
    );
  }, [rows]);

  const buildDailyRowsFromRecords = useCallback(
    (
      sourceRecords: CompletedJobOrderPickOrderDashboardRecord[],
      startDate: dayjs.Dayjs,
      endDate: dayjs.Dayjs,
      selectedFloor: FloorFilter,
    ): DailySummaryRow[] => {
      const summaryMap = new Map<string, DailySummaryRow>();
      const start = startDate.startOf("day");
      const end = endDate.endOf("day");

      sourceRecords.filter(hasPlasticQty).forEach((record) => {
        const recordDay = parseRecordDate(record);
        if (!recordDay.isValid() || recordDay.isBefore(start) || recordDay.isAfter(end)) {
          return;
        }

        const dayKey = recordDay.format("YYYY-MM-DD");
        const current = summaryMap.get(dayKey) ?? {
          date: dayKey,
          floor2F: 0,
          floor3F: 0,
          floor4F: 0,
          total: 0,
        };

        addRecordQty(current, record, selectedFloor);
        summaryMap.set(dayKey, current);
      });

      return Array.from(summaryMap.values()).sort((a, b) => a.date.localeCompare(b.date));
    },
    [],
  );

  const calcSummary = useCallback((dailyRows: DailySummaryRow[]) => {
    return dailyRows.reduce(
      (acc, row) => {
        acc.floor2F += row.floor2F;
        acc.floor3F += row.floor3F;
        acc.floor4F += row.floor4F;
        acc.total += row.total;
        return acc;
      },
      { floor2F: 0, floor3F: 0, floor4F: 0, total: 0 },
    );
  }, []);

  const styleWorksheet = useCallback((worksheet: XLSX.WorkSheet, dataRowsCount: number) => {
    const summaryTitleRow = 4 + dataRowsCount;
    const summaryStartRow = 5 + dataRowsCount;

    worksheet["!cols"] = [{ wch: 16 }, { wch: 14 }, { wch: 14 }, { wch: 14 }, { wch: 14 }];
    worksheet["!merges"] = [
      { s: { r: 0, c: 0 }, e: { r: 0, c: 4 } },
      { s: { r: summaryTitleRow, c: 0 }, e: { r: summaryTitleRow, c: 4 } },
    ];

    const titleStyle = {
      font: { bold: true, sz: 14, color: { rgb: "1F2D3D" } },
      alignment: { horizontal: "center", vertical: "center" },
      fill: { fgColor: { rgb: "EAF3FF" } },
    };
    const headerStyle = {
      font: { bold: true, color: { rgb: "FFFFFF" } },
      fill: { fgColor: { rgb: "1976D2" } },
      alignment: { horizontal: "center", vertical: "center" },
      border: {
        top: { style: "thin", color: { rgb: "B0BEC5" } },
        bottom: { style: "thin", color: { rgb: "B0BEC5" } },
        left: { style: "thin", color: { rgb: "B0BEC5" } },
        right: { style: "thin", color: { rgb: "B0BEC5" } },
      },
    };
    const cellStyle = {
      alignment: { vertical: "center" },
      border: {
        top: { style: "thin", color: { rgb: "D0D7DE" } },
        bottom: { style: "thin", color: { rgb: "D0D7DE" } },
        left: { style: "thin", color: { rgb: "D0D7DE" } },
        right: { style: "thin", color: { rgb: "D0D7DE" } },
      },
    };
    const numberStyle = {
      ...cellStyle,
      alignment: { horizontal: "right", vertical: "center" },
      numFmt: "#,##0",
    };
    const summaryTitleStyle = {
      font: { bold: true, color: { rgb: "1F2D3D" } },
      fill: { fgColor: { rgb: "F1F8E9" } },
      alignment: { horizontal: "left", vertical: "center" },
    };

    for (let c = 0; c <= 4; c += 1) {
      const headerCell = XLSX.utils.encode_cell({ r: 2, c });
      if (worksheet[headerCell]) worksheet[headerCell].s = headerStyle;
    }

    for (let r = 3; r < 3 + dataRowsCount; r += 1) {
      for (let c = 0; c <= 4; c += 1) {
        const addr = XLSX.utils.encode_cell({ r, c });
        if (!worksheet[addr]) continue;
        worksheet[addr].s = c === 0 ? cellStyle : numberStyle;
      }
    }

    for (let r = summaryStartRow; r <= summaryStartRow + 3; r += 1) {
      const labelAddr = XLSX.utils.encode_cell({ r, c: 0 });
      const valueAddr = XLSX.utils.encode_cell({ r, c: 1 });
      if (worksheet[labelAddr]) worksheet[labelAddr].s = cellStyle;
      if (worksheet[valueAddr]) worksheet[valueAddr].s = numberStyle;
    }

    if (worksheet["A1"]) worksheet["A1"].s = titleStyle;
    const summaryTitleAddr = XLSX.utils.encode_cell({ r: summaryTitleRow, c: 0 });
    if (worksheet[summaryTitleAddr]) worksheet[summaryTitleAddr].s = summaryTitleStyle;
  }, []);

  const addReportSheet = useCallback(
    (
      workbook: XLSX.WorkBook,
      sheetName: string,
      reportTitle: string,
      dailyRows: DailySummaryRow[],
    ) => {
      const reportSummary = calcSummary(dailyRows);
      const aoa: (string | number)[][] = [
        [reportTitle, "", "", "", ""],
        ["", "", "", "", ""],
        [
          t("Date"),
          t("2/F plastic box carton qty count"),
          t("3/F plastic box carton qty count"),
          t("4/F plastic box carton qty count"),
          t("Total plastic box carton qty"),
        ],
        ...dailyRows.map((row) => [row.date, row.floor2F, row.floor3F, row.floor4F, row.total]),
        ["", "", "", "", ""],
        [t("Summary"), "", "", "", ""],
        [t("2/F plastic box carton qty count"), reportSummary.floor2F, "", "", ""],
        [t("3/F plastic box carton qty count"), reportSummary.floor3F, "", "", ""],
        [t("4/F plastic box carton qty count"), reportSummary.floor4F, "", "", ""],
        [t("Total plastic box carton qty"), reportSummary.total, "", "", ""],
      ];

      const worksheet = XLSX.utils.aoa_to_sheet(aoa);
      styleWorksheet(worksheet, dailyRows.length);
      XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
    },
    [calcSummary, styleWorksheet, t],
  );

  const handleDownloadExcel = useCallback(async () => {
    if (exportInFlightRef.current) return;
    exportInFlightRef.current = true;
    setIsExporting(true);
    try {
      const baseDate = dayjs(date || undefined).isValid() ? dayjs(date) : dayjs();
      const rangeFrom = baseDate.startOf("year").format("YYYY-MM-DD");
      const rangeTo = baseDate.endOf("year").format("YYYY-MM-DD");
      const allRecords = await fetchPlasticBoxCartonQtyDashboard(rangeFrom, rangeTo);
      const floorLabel =
        floor === "all" ? t("All floors") : floor;
      const dateLabel = baseDate.format("YYYY-MM-DD");

      const last7Rows = buildDailyRowsFromRecords(
        allRecords,
        baseDate.subtract(6, "day"),
        baseDate,
        floor,
      );
      const monthRows = buildDailyRowsFromRecords(
        allRecords,
        baseDate.startOf("month"),
        baseDate.endOf("month"),
        floor,
      );
      const yearRows = buildDailyRowsFromRecords(
        allRecords,
        baseDate.startOf("year"),
        baseDate.endOf("year"),
        floor,
      );

      const workbook = XLSX.utils.book_new();
      addReportSheet(
        workbook,
        t("Last 7 days"),
        `${t("Plastic box carton qty report last 7 days")} - ${floorLabel} - ${dateLabel}`,
        last7Rows,
      );
      addReportSheet(
        workbook,
        t("This month"),
        `${t("Plastic box carton qty report this month")} - ${floorLabel} - ${baseDate.format("YYYY年MM月")}`,
        monthRows,
      );
      addReportSheet(
        workbook,
        t("This year"),
        `${t("Plastic box carton qty report this year")} - ${floorLabel} - ${baseDate.format("YYYY年")}`,
        yearRows,
      );

      XLSX.writeFile(
        workbook,
        `${t("Plastic box carton qty multi period report")}_${floorLabel.replace("/", "")}_${dateLabel}.xlsx`,
      );
    } finally {
      setIsExporting(false);
      exportInFlightRef.current = false;
    }
  }, [date, floor, buildDailyRowsFromRecords, addReportSheet, t]);

  return (
    <Box sx={{ width: "100%" }}>
      <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ mb: 2 }}>
        <Typography variant="h6">{t("Plastic box carton qty dashboard")}</Typography>
        <Button
          variant="contained"
          onClick={handleDownloadExcel}
          disabled={loading || isExporting}
        >
          {isExporting ? t("Exporting...") : t("Download Excel")}
        </Button>
      </Stack>

      {error && (
        <Alert severity="error" sx={{ mb: 2 }}>
          {error}
        </Alert>
      )}

      {loading ? (
        <Box sx={{ py: 6, display: "flex", justifyContent: "center" }}>
          <CircularProgress />
        </Box>
      ) : (
        <Stack spacing={2}>
          <Grid container spacing={1.5}>
            <Grid item xs={12} md={6}>
              <TextField
                select
                fullWidth
                label={t("Floor")}
                value={floor}
                onChange={(event) => setFloor(event.target.value as FloorFilter)}
              >
                <MenuItem value="all">{t("All")}</MenuItem>
                <MenuItem value="2/F">2/F</MenuItem>
                <MenuItem value="3/F">3/F</MenuItem>
                <MenuItem value="4/F">4/F</MenuItem>
              </TextField>
            </Grid>
            <Grid item xs={12} md={6}>
              <TextField
                fullWidth
                label={t("Date")}
                type="date"
                value={date}
                InputLabelProps={{ shrink: true }}
                onChange={(event) => setDate(event.target.value)}
              />
            </Grid>
          </Grid>

          <Grid container spacing={1.5} alignItems="stretch">
            <Grid item xs={12} md={4}>
              <TableContainer component={Paper} sx={{ height: "100%" }}>
                <Table size="small">
                  <TableBody>
                    <TableRow>
                      <TableCell>{t("2/F plastic box carton qty count")}</TableCell>
                      <TableCell align="right">
                        {summary.floor2F.toLocaleString("zh-HK")}
                      </TableCell>
                    </TableRow>
                    <TableRow>
                      <TableCell>{t("3/F plastic box carton qty count")}</TableCell>
                      <TableCell align="right">
                        {summary.floor3F.toLocaleString("zh-HK")}
                      </TableCell>
                    </TableRow>
                    <TableRow>
                      <TableCell>{t("4/F plastic box carton qty count")}</TableCell>
                      <TableCell align="right">
                        {summary.floor4F.toLocaleString("zh-HK")}
                      </TableCell>
                    </TableRow>
                    <TableRow>
                      <TableCell>{t("Total plastic box carton qty")}</TableCell>
                      <TableCell align="right">
                        {summary.total.toLocaleString("zh-HK")}
                      </TableCell>
                    </TableRow>
                  </TableBody>
                </Table>
              </TableContainer>
            </Grid>
            <Grid item xs={12} md={8}>
              <Paper sx={{ p: 1.5, height: "100%" }}>
                <SafeApexCharts
                  type="bar"
                  height={240}
                  options={chartOptions}
                  series={chartSeries}
                  chartRevision={`${floor}-${date}-${rows.length}`}
                />
              </Paper>
            </Grid>
          </Grid>
        </Stack>
      )}
    </Box>
  );
};

export default PlasticBoxCartonDashboardTab;
