"use client";

import React, { useCallback, useState } from "react";
import {
  Box,
  Typography,
  Skeleton,
  Alert,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  Checkbox,
  ListItemText,
} from "@mui/material";
import TrendingUp from "@mui/icons-material/TrendingUp";
import {
  fetchProductionScheduleByDate,
  fetchPlannedOutputByDateAndItem,
} from "@/app/api/chart/client";
import ChartCard from "../_components/ChartCard";
import DateRangeSelect from "../_components/DateRangeSelect";
import { toDateRange, DEFAULT_RANGE_DAYS } from "../_components/constants";
import SafeApexCharts from "@/components/charts/SafeApexCharts";

const PAGE_TITLE = "預測與計劃";

const DISTINCT_ITEM_COLORS = [
  "#d60000",
  "#018700",
  "#b500ff",
  "#05acc6",
  "#97ff00",
  "#ffa52f",
  "#ff8ec8",
  "#79525f",
  "#00fdcf",
  "#afa5ff",
  "#93ac83",
  "#9a6900",
  "#366962",
  "#d3008c",
  "#fdf490",
  "#c86e66",
  "#9ee2ff",
  "#00c846",
  "#ffa6b8",
  "#5f7a78",
  "#da81ff",
  "#ffc93d",
  "#4b5600",
  "#ff54a8",
  "#25bfff",
  "#4b3b00",
  "#ff7a00",
  "#8ed4a8",
  "#6e4b87",
  "#91b8ff",
  "#a03f00",
  "#00b395",
  "#c8a2c8",
  "#e67e22",
  "#16a085",
  "#8e44ad",
  "#2ecc71",
  "#f1c40f",
  "#e74c3c",
  "#2980b9",
  "#27ae60",
  "#f39c12",
  "#c0392b",
  "#1abc9c",
  "#9b59b6",
  "#34495e",
  "#ff1493",
  "#00ced1",
  "#7fff00",
  "#ff4500",
  "#00ff7f",
  "#4169e1",
  "#ff00ff",
  "#00bfff",
  "#ff6347",
  "#32cd32",
  "#ffd700",
  "#8b0000",
  "#006400",
  "#4b0082",
  "#b22222",
  "#228b22",
  "#00008b",
  "#ff69b4",
  "#20b2aa",
  "#ffb6c1",
  "#87cefa",
  "#adff2f",
  "#ffdead",
  "#40e0d0",
  "#ff7f50",
  "#7b68ee",
];

function getItemCodeColor(itemCode: string): string {
  let hash = 0;
  for (let i = 0; i < itemCode.length; i += 1) {
    hash = (hash * 31 + itemCode.charCodeAt(i)) | 0;
  }
  return DISTINCT_ITEM_COLORS[Math.abs(hash) % DISTINCT_ITEM_COLORS.length];
}

type Criteria = {
  prodSchedule: { rangeDays: number };
  plannedOutputByDate: { rangeDays: number; itemCodes: string[] };
};

const defaultCriteria: Criteria = {
  prodSchedule: { rangeDays: DEFAULT_RANGE_DAYS },
  plannedOutputByDate: { rangeDays: DEFAULT_RANGE_DAYS, itemCodes: [] },
};

export default function ForecastChartPage() {
  const [criteria, setCriteria] = useState<Criteria>(defaultCriteria);
  const [error, setError] = useState<string | null>(null);
  const [chartData, setChartData] = useState<{
    prodSchedule: { date: string; scheduledItemCount: number; totalEstProdCount: number }[];
    plannedOutputByDate: { date: string; itemCode: string; itemName: string; qty: number }[];
  }>({ prodSchedule: [], plannedOutputByDate: [] });
  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 { startDate: s, endDate: e } = toDateRange(criteria.prodSchedule.rangeDays);
    setChartLoading("prodSchedule", true);
    fetchProductionScheduleByDate(s, e)
      .then((data) =>
        setChartData((prev) => ({
          ...prev,
          prodSchedule: data as {
            date: string;
            scheduledItemCount: number;
            totalEstProdCount: number;
          }[],
        }))
      )
      .catch((err) => setError(err instanceof Error ? err.message : "Request failed"))
      .finally(() => setChartLoading("prodSchedule", false));
  }, [criteria.prodSchedule, setChartLoading]);

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

  const plannedOutputRows = chartData.plannedOutputByDate;
  const plannedOutputItemOptions = Array.from(
    new Map(plannedOutputRows.map((r) => [r.itemCode, { itemCode: r.itemCode, itemName: r.itemName || "" }])).values()
  ).sort((a, b) => a.itemCode.localeCompare(b.itemCode));
  const filteredPlannedOutputRows =
    criteria.plannedOutputByDate.itemCodes.length === 0
      ? plannedOutputRows
      : plannedOutputRows.filter((r) => criteria.plannedOutputByDate.itemCodes.includes(r.itemCode));

  const plannedOutputChart = React.useMemo(() => {
    const rows = filteredPlannedOutputRows;
    const dates = Array.from(new Set(rows.map((r) => r.date))).sort();
    const items = Array.from(
      new Map(rows.map((r) => [r.itemCode, { itemCode: r.itemCode, itemName: r.itemName || "" }])).values()
    ).sort((a, b) => a.itemCode.localeCompare(b.itemCode));
    const series = items.map(({ itemCode, itemName }) => ({
      name: [itemCode, itemName].filter(Boolean).join(" ") || itemCode,
      data: dates.map((d) => {
        const r = rows.find((x) => x.date === d && x.itemCode === itemCode);
        return r != null && r.qty != null ? Number(r.qty) : 0;
      }),
    }));
    const colors = items.map(({ itemCode }) => getItemCodeColor(itemCode));
    const hasData = dates.length > 0 && series.length > 0;
    // Remount chart when structure changes — avoids ApexCharts internal series/colors desync ("reading 'data'").
    const chartKey = `${dates.join(",")}|${items.map((i) => i.itemCode).join(",")}|${series.length}`;
    return { dates, series, colors, hasData, chartKey };
  }, [filteredPlannedOutputRows]);

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

      <ChartCard
        title="按物料計劃日產量（預測）"
        exportFilename="按物料計劃日產量_預測"
        exportData={filteredPlannedOutputRows.map((r) => ({ 日期: r.date, 物料編碼: r.itemCode, 物料名稱: r.itemName, 數量: r.qty }))}
        filters={
          <Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", alignItems: "center" }}>
            <DateRangeSelect
              value={criteria.plannedOutputByDate.rangeDays}
              onChange={(v) => updateCriteria("plannedOutputByDate", (c) => ({ ...c, rangeDays: v }))}
            />
            <FormControl size="small" sx={{ minWidth: 220 }}>
              <InputLabel>物料編碼</InputLabel>
              <Select
                multiple
                value={criteria.plannedOutputByDate.itemCodes}
                label="物料編碼"
                renderValue={(selected) =>
                  (selected as string[]).length === 0 ? "全部物料" : (selected as string[]).join(", ")
                }
                onChange={(e) =>
                  updateCriteria("plannedOutputByDate", (c) => ({
                    ...c,
                    itemCodes: typeof e.target.value === "string" ? e.target.value.split(",") : e.target.value,
                  }))
                }
              >
                {plannedOutputItemOptions.map((item) => (
                  <MenuItem key={item.itemCode} value={item.itemCode}>
                    <Checkbox checked={criteria.plannedOutputByDate.itemCodes.includes(item.itemCode)} />
                    <ListItemText primary={[item.itemCode, item.itemName].filter(Boolean).join(" - ")} />
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
          </Box>
        }
      >
        {loadingCharts.plannedOutputByDate ? (
          <Skeleton variant="rectangular" height={320} />
        ) : !plannedOutputChart.hasData ? (
          <Typography color="text.secondary" sx={{ py: 3 }}>
            此日期範圍內尚無排程資料。
          </Typography>
        ) : (
          <SafeApexCharts
            key={plannedOutputChart.chartKey}
            options={{
              chart: { type: "bar", animations: { enabled: false } },
              colors: plannedOutputChart.colors,
              xaxis: { categories: plannedOutputChart.dates },
              yaxis: { title: { text: "數量" } },
              plotOptions: { bar: { columnWidth: "60%" } },
              dataLabels: { enabled: false },
              legend: { position: "top", horizontalAlign: "left" },
            }}
            series={plannedOutputChart.series}
            type="bar"
            width="100%"
            height={Math.max(320, plannedOutputChart.dates.length * 24)}
          />
        )}
      </ChartCard>

      <ChartCard
        title="按日期生產排程（預估產量）"
        exportFilename="生產排程_按日期"
        exportData={chartData.prodSchedule.map((d) => ({ 日期: d.date, 已排物料: d.scheduledItemCount, 預估產量: d.totalEstProdCount }))}
        filters={
          <DateRangeSelect
            value={criteria.prodSchedule.rangeDays}
            onChange={(v) => updateCriteria("prodSchedule", (c) => ({ ...c, rangeDays: v }))}
          />
        }
      >
        {loadingCharts.prodSchedule ? (
          <Skeleton variant="rectangular" height={320} />
        ) : (
          <SafeApexCharts
            options={{
              chart: { type: "bar" },
              xaxis: { categories: chartData.prodSchedule.map((d) => d.date) },
              yaxis: { title: { text: "數量" } },
              plotOptions: { bar: { columnWidth: "60%" } },
              dataLabels: { enabled: false },
            }}
            series={[
              { name: "已排物料", data: chartData.prodSchedule.map((d) => d.scheduledItemCount) },
              { name: "預估產量", data: chartData.prodSchedule.map((d) => d.totalEstProdCount) },
            ]}
            type="bar"
            width="100%"
            height={320}
          />
        )}
      </ChartCard>
    </Box>
  );
}
