"use client";

import React, { useCallback, useState } from "react";
import { Box, Typography, Skeleton, Alert, TextField, Button, Chip, Stack } from "@mui/material";
import dynamic from "next/dynamic";
import dayjs from "dayjs";
import WarehouseIcon from "@mui/icons-material/Warehouse";
import {
  fetchStockTransactionsByDate,
  fetchStockInOutByDate,
  fetchStockBalanceTrend,
  fetchConsumptionTrendByMonth,
} from "@/app/api/chart/client";
import ChartCard from "../_components/ChartCard";
import DateRangeSelect from "../_components/DateRangeSelect";
import { toDateRange, DEFAULT_RANGE_DAYS, ITEM_CODE_DEBOUNCE_MS } from "../_components/constants";

const ApexCharts = dynamic(() => import("react-apexcharts"), { ssr: false });

const PAGE_TITLE = "庫存與倉儲";

type Criteria = {
  stockTxn: { rangeDays: number };
  stockInOut: { rangeDays: number };
  balance: { rangeDays: number };
  consumption: { rangeDays: number };
};

const defaultCriteria: Criteria = {
  stockTxn: { rangeDays: DEFAULT_RANGE_DAYS },
  stockInOut: { rangeDays: DEFAULT_RANGE_DAYS },
  balance: { rangeDays: DEFAULT_RANGE_DAYS },
  consumption: { rangeDays: DEFAULT_RANGE_DAYS },
};

export default function WarehouseChartPage() {
  const [criteria, setCriteria] = useState<Criteria>(defaultCriteria);
  const [itemCodeBalance, setItemCodeBalance] = useState("");
  const [debouncedItemCodeBalance, setDebouncedItemCodeBalance] = useState("");
  const [consumptionItemCodes, setConsumptionItemCodes] = useState<string[]>([]);
  const [consumptionItemCodeInput, setConsumptionItemCodeInput] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [chartData, setChartData] = useState<{
    stockTxn: { date: string; inQty: number; outQty: number; totalQty: number }[];
    stockInOut: { date: string; inQty: number; outQty: number }[];
    balance: { date: string; balance: number }[];
    consumption: { month: string; outQty: number }[];
    consumptionByItems?: { months: string[]; series: { name: string; data: number[] }[] };
  }>({ stockTxn: [], stockInOut: [], balance: [], consumption: [] });
  const [loadingCharts, setLoadingCharts] = useState<Record<string, boolean>>({});

  const updateCriteria = useCallback(
    <K extends keyof Criteria>(key: K, updater: (prev: Criteria[K]) => Criteria[K]) => {
      setCriteria((prev) => ({ ...prev, [key]: updater(prev[key]) }));
    },
    []
  );
  const setChartLoading = useCallback((key: string, value: boolean) => {
    setLoadingCharts((prev) => (prev[key] === value ? prev : { ...prev, [key]: value }));
  }, []);

  React.useEffect(() => {
    const t = setTimeout(() => setDebouncedItemCodeBalance(itemCodeBalance), ITEM_CODE_DEBOUNCE_MS);
    return () => clearTimeout(t);
  }, [itemCodeBalance]);
  const addConsumptionItem = useCallback(() => {
    const code = consumptionItemCodeInput.trim();
    if (!code || consumptionItemCodes.includes(code)) return;
    setConsumptionItemCodes((prev) => [...prev, code].sort());
    setConsumptionItemCodeInput("");
  }, [consumptionItemCodeInput, consumptionItemCodes]);

  React.useEffect(() => {
    const { startDate: s, endDate: e } = toDateRange(criteria.stockTxn.rangeDays);
    setChartLoading("stockTxn", true);
    fetchStockTransactionsByDate(s, e)
      .then((data) =>
        setChartData((prev) => ({
          ...prev,
          stockTxn: data as { date: string; inQty: number; outQty: number; totalQty: number }[],
        }))
      )
      .catch((err) => setError(err instanceof Error ? err.message : "Request failed"))
      .finally(() => setChartLoading("stockTxn", false));
  }, [criteria.stockTxn, setChartLoading]);

  React.useEffect(() => {
    const { startDate: s, endDate: e } = toDateRange(criteria.stockInOut.rangeDays);
    setChartLoading("stockInOut", true);
    fetchStockInOutByDate(s, e)
      .then((data) =>
        setChartData((prev) => ({
          ...prev,
          stockInOut: data as { date: string; inQty: number; outQty: number }[],
        }))
      )
      .catch((err) => setError(err instanceof Error ? err.message : "Request failed"))
      .finally(() => setChartLoading("stockInOut", false));
  }, [criteria.stockInOut, setChartLoading]);

  React.useEffect(() => {
    const { startDate: s, endDate: e } = toDateRange(criteria.balance.rangeDays);
    const item = debouncedItemCodeBalance.trim() || undefined;
    setChartLoading("balance", true);
    fetchStockBalanceTrend(s, e, item)
      .then((data) =>
        setChartData((prev) => ({
          ...prev,
          balance: data as { date: string; balance: number }[],
        }))
      )
      .catch((err) => setError(err instanceof Error ? err.message : "Request failed"))
      .finally(() => setChartLoading("balance", false));
  }, [criteria.balance, debouncedItemCodeBalance, setChartLoading]);

  React.useEffect(() => {
    const { startDate: s, endDate: e } = toDateRange(criteria.consumption.rangeDays);
    setChartLoading("consumption", true);
    if (consumptionItemCodes.length === 0) {
      fetchConsumptionTrendByMonth(dayjs().year(), s, e, undefined)
        .then((data) =>
          setChartData((prev) => ({
            ...prev,
            consumption: data as { month: string; outQty: number }[],
            consumptionByItems: undefined,
          }))
        )
        .catch((err) => setError(err instanceof Error ? err.message : "Request failed"))
        .finally(() => setChartLoading("consumption", false));
      return;
    }
    Promise.all(
      consumptionItemCodes.map((code) =>
        fetchConsumptionTrendByMonth(dayjs().year(), s, e, code)
      )
    )
      .then((results) => {
        const byItem = results.map((rows, i) => ({
          itemCode: consumptionItemCodes[i],
          rows: rows as { month: string; outQty: number }[],
        }));
        const allMonths = Array.from(
          new Set(byItem.flatMap((x) => x.rows.map((r) => r.month)))
        ).sort();
        const series = byItem.map(({ itemCode, rows }) => ({
          name: itemCode,
          data: allMonths.map((m) => {
            const r = rows.find((x) => x.month === m);
            return r ? r.outQty : 0;
          }),
        }));
        setChartData((prev) => ({
          ...prev,
          consumption: [],
          consumptionByItems: { months: allMonths, series },
        }));
      })
      .catch((err) => setError(err instanceof Error ? err.message : "Request failed"))
      .finally(() => setChartLoading("consumption", false));
  }, [criteria.consumption, consumptionItemCodes, setChartLoading]);

  return (
    <Box sx={{ maxWidth: 1200, mx: "auto" }}>
      <Typography variant="h5" sx={{ mb: 2, fontWeight: 600, display: "flex", alignItems: "center", gap: 1 }}>
        <WarehouseIcon /> {PAGE_TITLE}
      </Typography>
      {error && (
        <Alert severity="error" sx={{ mb: 2 }} onClose={() => setError(null)}>
          {error}
        </Alert>
      )}

      <ChartCard
        title="按日期庫存流水（入/出/合計）"
        exportFilename="庫存流水_按日期"
        exportData={chartData.stockTxn.map((s) => ({ 日期: s.date, 入庫: s.inQty, 出庫: s.outQty, 合計: s.totalQty }))}
        filters={
          <DateRangeSelect
            value={criteria.stockTxn.rangeDays}
            onChange={(v) => updateCriteria("stockTxn", (c) => ({ ...c, rangeDays: v }))}
          />
        }
      >
        {loadingCharts.stockTxn ? (
          <Skeleton variant="rectangular" height={320} />
        ) : (
          <ApexCharts
            options={{
              chart: { type: "line" },
              xaxis: { categories: chartData.stockTxn.map((s) => s.date) },
              yaxis: { title: { text: "數量" } },
              stroke: { curve: "smooth" },
              dataLabels: { enabled: false },
            }}
            series={[
              { name: "入庫", data: chartData.stockTxn.map((s) => s.inQty) },
              { name: "出庫", data: chartData.stockTxn.map((s) => s.outQty) },
              { name: "合計", data: chartData.stockTxn.map((s) => s.totalQty) },
            ]}
            type="line"
            width="100%"
            height={320}
          />
        )}
      </ChartCard>

      <ChartCard
        title="按日期入庫與出庫"
        exportFilename="入庫與出庫_按日期"
        exportData={chartData.stockInOut.map((s) => ({ 日期: s.date, 入庫: s.inQty, 出庫: s.outQty }))}
        filters={
          <DateRangeSelect
            value={criteria.stockInOut.rangeDays}
            onChange={(v) => updateCriteria("stockInOut", (c) => ({ ...c, rangeDays: v }))}
          />
        }
      >
        {loadingCharts.stockInOut ? (
          <Skeleton variant="rectangular" height={320} />
        ) : (
          <ApexCharts
            options={{
              chart: { type: "area", stacked: false },
              xaxis: { categories: chartData.stockInOut.map((s) => s.date) },
              yaxis: { title: { text: "數量" } },
              stroke: { curve: "smooth" },
              dataLabels: { enabled: false },
            }}
            series={[
              { name: "入庫", data: chartData.stockInOut.map((s) => s.inQty) },
              { name: "出庫", data: chartData.stockInOut.map((s) => s.outQty) },
            ]}
            type="area"
            width="100%"
            height={320}
          />
        )}
      </ChartCard>

      <ChartCard
        title="庫存餘額趨勢"
        exportFilename="庫存餘額趨勢"
        exportData={chartData.balance.map((b) => ({ 日期: b.date, 餘額: b.balance }))}
        filters={
          <>
            <DateRangeSelect
              value={criteria.balance.rangeDays}
              onChange={(v) => updateCriteria("balance", (c) => ({ ...c, rangeDays: v }))}
            />
            <TextField
              size="small"
              label="物料編碼"
              placeholder="可選"
              value={itemCodeBalance}
              onChange={(e) => setItemCodeBalance(e.target.value)}
              sx={{ minWidth: 180 }}
            />
          </>
        }
      >
        {loadingCharts.balance ? (
          <Skeleton variant="rectangular" height={320} />
        ) : (
          <ApexCharts
            options={{
              chart: { type: "line" },
              xaxis: { categories: chartData.balance.map((b) => b.date) },
              yaxis: { title: { text: "餘額" } },
              stroke: { curve: "smooth" },
              dataLabels: { enabled: false },
            }}
            series={[{ name: "餘額", data: chartData.balance.map((b) => b.balance) }]}
            type="line"
            width="100%"
            height={320}
          />
        )}
      </ChartCard>

      <ChartCard
        title="按月考勤消耗趨勢（出庫量）"
        exportFilename="按月考勤消耗趨勢_出庫量"
        exportData={
          chartData.consumptionByItems
            ? chartData.consumptionByItems.series.flatMap((s) =>
                s.data.map((qty, i) => ({
                  月份: chartData.consumptionByItems!.months[i],
                  物料編碼: s.name,
                  出庫量: qty,
                }))
              )
            : chartData.consumption.map((c) => ({ 月份: c.month, 出庫量: c.outQty }))
        }
        filters={
          <>
            <DateRangeSelect
              value={criteria.consumption.rangeDays}
              onChange={(v) => updateCriteria("consumption", (c) => ({ ...c, rangeDays: v }))}
            />
            <Stack direction="row" alignItems="center" flexWrap="wrap" gap={1}>
              <TextField
                size="small"
                label="物料編碼"
                placeholder={consumptionItemCodes.length === 0 ? "不選則全部合計" : "新增物料以分項顯示"}
                value={consumptionItemCodeInput}
                onChange={(e) => setConsumptionItemCodeInput(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && (e.preventDefault(), addConsumptionItem())}
                sx={{ minWidth: 180 }}
              />
              <Button size="small" variant="outlined" onClick={addConsumptionItem}>
                新增
              </Button>
              {consumptionItemCodes.map((code) => (
                <Chip
                  key={code}
                  label={code}
                  size="small"
                  onDelete={() =>
                    setConsumptionItemCodes((prev) => prev.filter((c) => c !== code))
                  }
                />
              ))}
            </Stack>
          </>
        }
      >
        {loadingCharts.consumption ? (
          <Skeleton variant="rectangular" height={320} />
        ) : chartData.consumptionByItems ? (
          <ApexCharts
            options={{
              chart: { type: "bar", stacked: false },
              xaxis: { categories: chartData.consumptionByItems.months },
              yaxis: { title: { text: "出庫量" } },
              plotOptions: { bar: { columnWidth: "60%" } },
              dataLabels: { enabled: false },
              legend: { position: "top" },
            }}
            series={chartData.consumptionByItems.series}
            type="bar"
            width="100%"
            height={320}
          />
        ) : (
          <ApexCharts
            options={{
              chart: { type: "bar" },
              xaxis: { categories: chartData.consumption.map((c) => c.month) },
              yaxis: { title: { text: "出庫量" } },
              plotOptions: { bar: { columnWidth: "60%" } },
              dataLabels: { enabled: false },
            }}
            series={[{ name: "出庫量", data: chartData.consumption.map((c) => c.outQty) }]}
            type="bar"
            width="100%"
            height={320}
          />
        )}
      </ChartCard>
    </Box>
  );
}
