"use client";

import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
  Box,
  Typography,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Paper,
  TextField,
  Alert,
  CircularProgress,
  Stack,
  Button,
  Chip,
  Tooltip,
  FormControl,
  FormControlLabel,
  InputLabel,
  MenuItem,
  Select,
  Switch,
} from "@mui/material";
import { alpha, useTheme } from "@mui/material/styles";
import Link from "next/link";
import dayjs from "dayjs";
import Microwave from "@mui/icons-material/Microwave";
import AccountTree from "@mui/icons-material/AccountTree";
import FilterAltOutlined from "@mui/icons-material/FilterAltOutlined";
import { fetchEquipmentUsageBoard, type EquipmentUsageBoardRow } from "@/app/api/chart/client";
import SafeApexCharts from "@/components/charts/SafeApexCharts";
import { CHART_BOARD_REFRESH_INTERVAL_SEC_OPTIONS } from "@/app/(main)/chart/chartBoardRefreshPrefs";
import { useChartBoardRefreshPrefs } from "@/app/(main)/chart/useChartBoardRefreshPrefs";

const EQUIPMENT_CHART_MAX = 35;

/** Stable key for grouping / filter (master equipment id or free-text label). */
function rowEquipmentKey(r: EquipmentUsageBoardRow): string {
  if (r.equipmentId > 0) return `id:${r.equipmentId}`;
  const c = (r.equipmentCode ?? "").trim();
  const n = (r.equipmentName ?? "").trim();
  return `txt:${c}\u0001${n}`;
}

/** Single display line when code/name may duplicate (equipment or process). */
function formatCodeNameLine(code: string, name: string): string {
  const c = (code ?? "").trim();
  const n = (name ?? "").trim();
  if (!c && !n) return "—";
  if (!c) return n;
  if (!n) return c;
  if (c.toLowerCase() === n.toLowerCase()) return n;
  if (n.toLowerCase().startsWith(`${c.toLowerCase()} `) || n.toLowerCase().startsWith(`${c.toLowerCase()}　`)) return n;
  if (n.length > c.length && n.toLowerCase().startsWith(c.toLowerCase())) {
    const after = n.slice(c.length, c.length + 1);
    if (/[\s\-–—:：·.|／/]/.test(after)) return n;
  }
  return `${c} ${n}`;
}

function formatUsageMinutes(m: number): string {
  if (!Number.isFinite(m) || m <= 0) return "—";
  const rounded = Math.round(m * 10) / 10;
  if (rounded < 60) return `${rounded} 分`;
  const h = Math.floor(rounded / 60);
  const mm = Math.round((rounded % 60) * 10) / 10;
  return mm > 0 ? `${h} 小時 ${mm} 分` : `${h} 小時`;
}

export default function EquipmentUsageBoardPage() {
  const theme = useTheme();
  /** Calendar day for API (local). Default: today. */
  const [viewDate, setViewDate] = useState(() => dayjs().format("YYYY-MM-DD"));
  const [rows, setRows] = useState<EquipmentUsageBoardRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [lastUpdated, setLastUpdated] = useState("");
  /** null = all equipment; otherwise rowEquipmentKey */
  const [selectedEquipmentKey, setSelectedEquipmentKey] = useState<string | null>(null);
  const { autoRefreshOn, setAutoRefreshOn, refreshIntervalSec, setRefreshIntervalSec } =
    useChartBoardRefreshPrefs("equipment");

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const data = await fetchEquipmentUsageBoard(viewDate);
      setRows(data);
      setLastUpdated(dayjs().format("YYYY-MM-DD HH:mm:ss"));
    } catch (e) {
      setError(e instanceof Error ? e.message : "Request failed");
    } finally {
      setLoading(false);
    }
  }, [viewDate]);

  useEffect(() => {
    void load();
  }, [load]);

  useEffect(() => {
    if (!autoRefreshOn || refreshIntervalSec < 10) return;
    const t = setInterval(() => void load(), refreshIntervalSec * 1000);
    return () => clearInterval(t);
  }, [load, autoRefreshOn, refreshIntervalSec]);

  useEffect(() => {
    setSelectedEquipmentKey(null);
  }, [viewDate]);

  useEffect(() => {
    const onKey = (ev: KeyboardEvent) => {
      const t = ev.target as HTMLElement | null;
      if (
        t &&
        (t.tagName === "INPUT" ||
          t.tagName === "TEXTAREA" ||
          t.tagName === "SELECT" ||
          t.isContentEditable)
      ) {
        return;
      }
      if (ev.ctrlKey || ev.metaKey || ev.altKey) return;
      if (ev.key === "t" || ev.key === "T") {
        ev.preventDefault();
        setViewDate(dayjs().format("YYYY-MM-DD"));
      }
      if (ev.key === "y" || ev.key === "Y") {
        ev.preventDefault();
        setViewDate(dayjs().subtract(1, "day").format("YYYY-MM-DD"));
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  const equipmentUsageChart = useMemo(() => {
    const map = new Map<string, { key: string; label: string; minutes: number }>();
    rows.forEach((r) => {
      const k = rowEquipmentKey(r);
      const label = formatCodeNameLine(r.equipmentCode, r.equipmentName);
      const add = Number.isFinite(r.usageMinutes) ? r.usageMinutes : 0;
      const cur = map.get(k) ?? { key: k, label, minutes: 0 };
      cur.minutes += add;
      map.set(k, cur);
    });
    const list = Array.from(map.values())
      .filter((x) => x.minutes > 0)
      .sort((a, b) => b.minutes - a.minutes)
      .slice(0, EQUIPMENT_CHART_MAX);
    return {
      keys: list.map((x) => x.key),
      categories: list.map((x) => (x.label.length > 34 ? `${x.label.slice(0, 32)}…` : x.label)),
      data: list.map((x) => Math.round(x.minutes * 10) / 10),
    };
  }, [rows]);

  const barClickRef = useRef<(index: number) => void>(() => {});
  barClickRef.current = (index: number) => {
    const key = equipmentUsageChart.keys[index];
    if (key == null) return;
    setSelectedEquipmentKey((prev) => (prev === key ? null : key));
  };

  const barOptions = useMemo(
    () => ({
      chart: {
        type: "bar" as const,
        toolbar: { show: false },
        events: {
          dataPointSelection: (_e: unknown, _ctx: unknown, cfg: { dataPointIndex?: number }) => {
            const i = cfg?.dataPointIndex;
            if (typeof i !== "number" || i < 0) return;
            barClickRef.current(i);
          },
        },
      },
      plotOptions: {
        bar: {
          horizontal: true,
          barHeight: "72%",
          borderRadius: 4,
          distributed: true,
        },
      },
      colors: ["#1976d2", "#0288d1", "#0097a7", "#00838f", "#00695c", "#2e7d32", "#558b2f", "#827717"],
      dataLabels: { enabled: true, formatter: (val: number) => (Number.isFinite(val) ? `${val} 分` : "") },
      xaxis: { categories: equipmentUsageChart.categories, title: { text: "分鐘" } },
      yaxis: { labels: { maxWidth: 260 } },
      legend: { show: false },
      tooltip: { y: { formatter: (val: number) => `${val} 分鐘` } },
    }),
    [equipmentUsageChart.categories],
  );

  const displayRows = useMemo(() => {
    if (!selectedEquipmentKey) return rows;
    return rows.filter((r) => rowEquipmentKey(r) === selectedEquipmentKey);
  }, [rows, selectedEquipmentKey]);

  const selectedLabel = useMemo(() => {
    if (!selectedEquipmentKey) return "";
    const hit = rows.find((r) => rowEquipmentKey(r) === selectedEquipmentKey);
    return hit ? formatCodeNameLine(hit.equipmentCode, hit.equipmentName) : selectedEquipmentKey;
  }, [rows, selectedEquipmentKey]);

  const stats = useMemo(() => {
    const working = displayRows.filter((r) => r.workingNow === 1).length;
    const eqKeys = new Set(displayRows.map((r) => rowEquipmentKey(r)));
    const totalMins = displayRows.reduce((s, r) => s + (Number.isFinite(r.usageMinutes) ? r.usageMinutes : 0), 0);
    return { working, sessions: displayRows.length, equipmentTouched: eqKeys.size, totalMins };
  }, [displayRows]);

  const isToday = viewDate === dayjs().format("YYYY-MM-DD");
  const weekdayZh = ["日", "一", "二", "三", "四", "五", "六"][dayjs(viewDate).day()] ?? "";

  return (
    <Box
      sx={{
        width: "100%",
        maxWidth: "100%",
        mx: "auto",
        p: { xs: 0.5, sm: 1 },
        boxSizing: "border-box",
      }}
    >
      <Typography variant="h5" sx={{ mb: 1, fontWeight: 600, display: "flex", alignItems: "center", gap: 1 }}>
        <Microwave /> 設備使用看板
      </Typography>
      <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
        資料來源與<strong>工單編輯／工藝流程</strong>一致。上方<strong>使用時間（分鐘）</strong>為各設備當日明細加總（有起訖則相減；產線 Pass/無完工時間時用預設生產分鐘）。
        點<strong>長條圖</strong>可篩選下方列表，再點同一項取消。
        <strong> 快捷鍵</strong>（不在輸入框內時）：<kbd style={{ padding: "1px 6px", borderRadius: 4, border: "1px solid #ccc" }}>T</kbd>{" "}
        今日、<kbd style={{ padding: "1px 6px", borderRadius: 4, border: "1px solid #ccc" }}>Y</kbd> 昨日。
        {autoRefreshOn
          ? ` 已開啟自動重新整理（每 ${refreshIntervalSec} 秒）`
          : " 預設不自動更新，可開啟「自動重新整理」並選擇間隔。"}
        {" 設定自動儲存在本機（登入時依帳號；未登入則為此分頁工作階段）。"}
        {lastUpdated ? ` · 最後更新 ${lastUpdated}` : ""}
      </Typography>

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

      <Stack
        direction={{ xs: "column", lg: "row" }}
        spacing={2}
        alignItems={{ xs: "stretch", lg: "stretch" }}
        justifyContent={{ lg: "space-between" }}
        sx={{ mb: 2 }}
      >
        <Paper
          variant="outlined"
          sx={{
            p: 1.5,
            flex: { lg: "1 1 0" },
            minWidth: { xs: "100%", lg: 280 },
            borderColor: "divider",
            bgcolor: alpha(theme.palette.primary.main, 0.03),
          }}
        >
          <Typography
            variant="overline"
            color="text.secondary"
            sx={{ display: "block", mb: 1, lineHeight: 1.4, letterSpacing: 0.6 }}
          >
            查詢與列表
          </Typography>
          <Stack spacing={1.25}>
            <Typography variant="body2" color="text.secondary" sx={{ fontWeight: 600 }}>
              歸屬日 {viewDate}（週{weekdayZh}）
              {!isToday && <Chip size="small" label="非今日" sx={{ ml: 1 }} variant="outlined" />}
            </Typography>
            <Stack direction="row" flexWrap="wrap" useFlexGap alignItems="center" gap={1.25}>
              <Tooltip title="快捷鍵 T">
                <Button
                  size="small"
                  variant={isToday ? "contained" : "outlined"}
                  onClick={() => setViewDate(dayjs().format("YYYY-MM-DD"))}
                >
                  今日
                </Button>
              </Tooltip>
              <Tooltip title="快捷鍵 Y">
                <Button size="small" variant="outlined" onClick={() => setViewDate(dayjs().subtract(1, "day").format("YYYY-MM-DD"))}>
                  昨日
                </Button>
              </Tooltip>
              <TextField
                size="small"
                label="選擇日期"
                type="date"
                value={viewDate}
                onChange={(e) => setViewDate(e.target.value)}
                InputLabelProps={{ shrink: true }}
                sx={{ minWidth: 178 }}
              />
              <Button variant="outlined" size="small" onClick={() => void load()} disabled={loading}>
                重新整理
              </Button>
            </Stack>
          </Stack>
        </Paper>

        <Paper
          variant="outlined"
          sx={{
            p: 1.5,
            flex: { lg: "0 0 auto" },
            width: { xs: "100%", lg: "auto" },
            minWidth: { lg: 200 },
            borderColor: "divider",
            bgcolor: alpha(theme.palette.grey[500], 0.06),
          }}
        >
          <Typography
            variant="overline"
            color="text.secondary"
            sx={{ display: "block", mb: 1, lineHeight: 1.4, letterSpacing: 0.6 }}
          >
            其他看板
          </Typography>
          <Stack direction="column" spacing={1} sx={{ maxWidth: 220 }}>
            <Button component={Link} href="/chart/joborder/board" size="small" variant="outlined" fullWidth>
              工單即時看板
            </Button>
            <Button component={Link} href="/chart/process/board" size="small" variant="outlined" fullWidth startIcon={<AccountTree />}>
              工序即時看板
            </Button>
            <Button component={Link} href="/chart/joborder" size="small" variant="outlined" fullWidth>
              工單圖表
            </Button>
          </Stack>
        </Paper>

        <Paper
          variant="outlined"
          sx={{
            p: 1.5,
            flex: { lg: "0 0 auto" },
            width: { xs: "100%", lg: "auto" },
            minWidth: { xs: "100%", lg: 300 },
            borderColor: "divider",
            bgcolor: alpha(theme.palette.info.main, 0.04),
          }}
        >
          <Typography
            variant="overline"
            color="text.secondary"
            sx={{ display: "block", mb: 1, lineHeight: 1.4, letterSpacing: 0.6 }}
          >
            自動重新整理
          </Typography>
          <Stack direction="row" flexWrap="wrap" useFlexGap alignItems="center" gap={1.25}>
            <FormControlLabel
              control={
                <Switch
                  size="small"
                  checked={autoRefreshOn}
                  onChange={(_, v) => setAutoRefreshOn(v)}
                  inputProps={{ "aria-label": "自動重新整理" }}
                />
              }
              label="開啟"
              sx={{ ml: 0, mr: 0 }}
            />
            <FormControl size="small" sx={{ minWidth: 124 }} disabled={!autoRefreshOn}>
              <InputLabel id="eq-board-refresh-interval-label">間隔（秒）</InputLabel>
              <Select
                labelId="eq-board-refresh-interval-label"
                label="間隔（秒）"
                value={refreshIntervalSec}
                onChange={(e) => setRefreshIntervalSec(Number(e.target.value))}
              >
                {CHART_BOARD_REFRESH_INTERVAL_SEC_OPTIONS.map((sec) => (
                  <MenuItem key={sec} value={sec}>
                    {sec} 秒
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
          </Stack>
        </Paper>
      </Stack>

      {selectedEquipmentKey && (
        <Stack direction="row" alignItems="center" spacing={1} sx={{ mb: 2 }}>
          <FilterAltOutlined fontSize="small" color="action" />
          <Chip
            label={`篩選設備：${selectedLabel}`}
            onDelete={() => setSelectedEquipmentKey(null)}
            color="primary"
            variant="outlined"
          />
        </Stack>
      )}

      {!loading && rows.length > 0 && equipmentUsageChart.data.length > 0 && (
        <Paper variant="outlined" sx={{ p: 2, mb: 3 }}>
          <Typography variant="subtitle2" fontWeight={600} gutterBottom>
            使用時間（分鐘）— {viewDate}
          </Typography>
          <Typography variant="caption" color="text.secondary" display="block" sx={{ mb: 1 }}>
            點擊長條篩選下方明細（最多顯示 {EQUIPMENT_CHART_MAX} 台，依分鐘數由高到低）。
          </Typography>
          <SafeApexCharts
            chartRevision={JSON.stringify(equipmentUsageChart.keys)}
            options={barOptions}
            series={[{ name: "分鐘", data: equipmentUsageChart.data }]}
            type="bar"
            height={Math.min(520, 120 + equipmentUsageChart.data.length * 28)}
          />
        </Paper>
      )}

      {!loading && rows.length > 0 && equipmentUsageChart.data.length === 0 && (
        <Alert severity="info" sx={{ mb: 3 }}>
          當日有明細但無法加總使用分鐘（多數為缺開／完工時間且無預設生產分鐘）。仍可在下方表格檢視。
        </Alert>
      )}

      {!loading && (
        <Stack direction="row" spacing={2} useFlexGap flexWrap="wrap" sx={{ mb: 2 }}>
          <Paper variant="outlined" sx={{ px: 2, py: 1.5 }}>
            <Typography variant="caption" color="text.secondary">
              {selectedEquipmentKey ? "篩選後筆數" : "該日總筆數"}
            </Typography>
            <Typography variant="h6">{stats.sessions}</Typography>
          </Paper>
          <Paper variant="outlined" sx={{ px: 2, py: 1.5 }}>
            <Typography variant="caption" color="text.secondary">
              使用分鐘合計（篩選範圍）
            </Typography>
            <Typography variant="h6">{formatUsageMinutes(stats.totalMins)}</Typography>
          </Paper>
          <Paper variant="outlined" sx={{ px: 2, py: 1.5 }}>
            <Typography variant="caption" color="text.secondary">
              涉及設備數（篩選範圍）
            </Typography>
            <Typography variant="h6">{stats.equipmentTouched}</Typography>
          </Paper>
          {stats.working > 0 && (
            <Paper variant="outlined" sx={{ px: 2, py: 1.5 }}>
              <Typography variant="caption" color="text.secondary">
                設備工時未結案
              </Typography>
              <Typography variant="h6">{stats.working}</Typography>
            </Paper>
          )}
        </Stack>
      )}

      {loading && rows.length === 0 ? (
        <Box sx={{ display: "flex", justifyContent: "center", py: 6 }}>
          <CircularProgress />
        </Box>
      ) : rows.length === 0 ? (
        <Paper variant="outlined" sx={{ p: 4, textAlign: "center" }}>
          <Typography color="text.secondary">
            此日期沒有符合歸屬日的設備使用紀錄（含工藝流程明細），或該日尚無已完工且已填設備的步驟。
          </Typography>
        </Paper>
      ) : displayRows.length === 0 ? (
        <Paper variant="outlined" sx={{ p: 4, textAlign: "center" }}>
          <Typography color="text.secondary" sx={{ mb: 2 }}>
            此篩選下沒有明細。
          </Typography>
          <Button size="small" onClick={() => setSelectedEquipmentKey(null)}>
            清除設備篩選
          </Button>
        </Paper>
      ) : (
        <TableContainer component={Paper} variant="outlined">
          <Table size="small" stickyHeader>
            <TableHead>
              <TableRow>
                <TableCell>狀態</TableCell>
                <TableCell>設備</TableCell>
                <TableCell align="right">使用(分)</TableCell>
                <TableCell>工單</TableCell>
                <TableCell>工序</TableCell>
                <TableCell>工單計劃開始</TableCell>
                <TableCell>開工時間</TableCell>
                <TableCell>完工時間</TableCell>
                <TableCell>操作員</TableCell>
                <TableCell align="center">開啟</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {displayRows.map((r) => (
                <TableRow key={`${r.jobOrderId}-${r.jopdId}-${r.operatingEnd}-${r.operatingStart}`} hover>
                  <TableCell>
                    {r.workingNow === 1 ? (
                      <Chip label="設備工時未結案" size="small" color="warning" variant="outlined" />
                    ) : !r.operatingStart?.trim() && !r.operatingEnd?.trim() ? (
                      <Chip label="未填設備工時" size="small" color="default" variant="outlined" />
                    ) : (
                      <Chip label="已完工" size="small" variant="outlined" />
                    )}
                  </TableCell>
                  <TableCell sx={{ fontWeight: 600 }}>{formatCodeNameLine(r.equipmentCode, r.equipmentName)}</TableCell>
                  <TableCell align="right">{formatUsageMinutes(r.usageMinutes)}</TableCell>
                  <TableCell>{r.jobOrderCode || "—"}</TableCell>
                  <TableCell sx={{ maxWidth: 220 }}>{formatCodeNameLine(r.processCode, r.processName)}</TableCell>
                  <TableCell>{r.jobPlanStart || "—"}</TableCell>
                  <TableCell>{r.operatingStart || "—"}</TableCell>
                  <TableCell>{r.operatingEnd || "—"}</TableCell>
                  <TableCell>{r.operatorName || r.operatorUsername || "—"}</TableCell>
                  <TableCell align="center">
                    <Button
                      component={Link}
                      href={`/jo/edit?id=${r.jobOrderId}`}
                      target="_blank"
                      rel="noopener noreferrer"
                      size="small"
                    >
                      開啟
                    </Button>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </TableContainer>
      )}
    </Box>
  );
}
