"use client";

import React, { useCallback, useEffect, useState } from "react";
import {
  Alert,
  Box,
  Button,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Paper,
  Snackbar,
  Stack,
  TextField,
  Typography,
} from "@mui/material";
import ChevronLeft from "@mui/icons-material/ChevronLeft";
import ChevronRight from "@mui/icons-material/ChevronRight";
import Settings from "@mui/icons-material/Settings";
import {
  checkPrinterStatus,
  fetchLaserJobOrders,
  fetchLaserBag2Settings,
  type LaserLastReceiveSuccess,
  JobOrderListItem,
  patchSetting,
  sendLaserBag2Job,
} from "@/app/api/laserPrint/actions";
import dayjs from "dayjs";
import { formatHongKongDateTime } from "@/utils/formatHongKongDateTime";

const BG_TOP = "#E8F4FC";
const BG_LIST = "#D4E8F7";
const BG_ROW = "#C5E1F5";
const BG_ROW_SELECTED = "#6BB5FF";
const BG_STATUS_ERROR = "#FFCCCB";
const BG_STATUS_OK = "#90EE90";
const FG_STATUS_ERROR = "#B22222";
const FG_STATUS_OK = "#006400";

const REFRESH_MS = 60 * 1000;
const PRINTER_CHECK_MS = 60 * 1000;
const PRINTER_RETRY_MS = 30 * 1000;
const LASER_SEND_COUNT = 3;
const BETWEEN_SEND_MS = 3000;
const SUCCESS_SIGNAL_MS = 3500;

function formatQty(val: number | null | undefined): string {
  if (val == null) return "—";
  try {
    const n = Number(val);
    if (Number.isInteger(n)) return n.toLocaleString();
    return n
      .toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 })
      .replace(/\.?0+$/, "");
  } catch {
    return String(val);
  }
}

function getBatch(jo: JobOrderListItem): string {
  return (jo.lotNo || "—").trim() || "—";
}

function delay(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

const LaserPrintSearch: React.FC = () => {
  const [planDate, setPlanDate] = useState(() => dayjs().format("YYYY-MM-DD"));
  const [jobOrders, setJobOrders] = useState<JobOrderListItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [connected, setConnected] = useState(false);
  const [selectedId, setSelectedId] = useState<number | null>(null);
  const [sendingJobId, setSendingJobId] = useState<number | null>(null);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [errorSnackbar, setErrorSnackbar] = useState<{ open: boolean; message: string }>({
    open: false,
    message: "",
  });
  const [successSignal, setSuccessSignal] = useState<string | null>(null);
  const [laserHost, setLaserHost] = useState("192.168.18.77");
  const [laserPort, setLaserPort] = useState("45678");
  const [laserItemCodes, setLaserItemCodes] = useState("PP1175");
  const [lastLaserReceive, setLastLaserReceive] = useState<LaserLastReceiveSuccess | null>(null);
  const [settingsLoaded, setSettingsLoaded] = useState(false);
  const [printerConnected, setPrinterConnected] = useState(false);
  const [printerMessage, setPrinterMessage] = useState("檸檬機(激光機)未連接");

  const loadSystemSettings = useCallback(async () => {
    try {
      const s = await fetchLaserBag2Settings();
      setLaserHost(s.host);
      setLaserPort(String(s.port));
      setLaserItemCodes(s.itemCodes ?? "PP1175");
      setLastLaserReceive(s.lastReceiveSuccess ?? null);
      setSettingsLoaded(true);
    } catch (e) {
      setLastLaserReceive(null);
      setErrorSnackbar({
        open: true,
        message: e instanceof Error ? e.message : "無法載入系統設定",
      });
      setSettingsLoaded(true);
    }
  }, []);

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

  useEffect(() => {
    if (!successSignal) return;
    const t = setTimeout(() => setSuccessSignal(null), SUCCESS_SIGNAL_MS);
    return () => clearTimeout(t);
  }, [successSignal]);

  const loadJobOrders = useCallback(
    async (fromUserChange = false) => {
      setLoading(true);
      setError(null);
      try {
        const data = await fetchLaserJobOrders(planDate);
        setJobOrders(data);
        setConnected(true);
        if (fromUserChange) setSelectedId(null);
      } catch (e) {
        setError(e instanceof Error ? e.message : "連接不到服務器");
        setConnected(false);
        setJobOrders([]);
      } finally {
        setLoading(false);
      }
    },
    [planDate],
  );

  useEffect(() => {
    void loadJobOrders(true);
  }, [planDate]);

  useEffect(() => {
    if (!connected) return;
    const id = setInterval(() => void loadJobOrders(false), REFRESH_MS);
    return () => clearInterval(id);
  }, [connected, loadJobOrders]);

  /** Server uses DB LASER_PRINT.host/port (omit body) so UI matches /plastic/print-laser-bag2. */
  const checkLaser = useCallback(async () => {
    try {
      const result = await checkPrinterStatus({ printerType: "laser" });
      setPrinterConnected(result.connected);
      setPrinterMessage(result.message);
    } catch (e) {
      setPrinterConnected(false);
      setPrinterMessage(e instanceof Error ? e.message : "檸檬機(激光機)狀態檢查失敗");
    }
  }, []);

  useEffect(() => {
    if (!settingsLoaded) return;
    void checkLaser();
  }, [settingsLoaded, checkLaser]);

  useEffect(() => {
    if (!settingsLoaded) return;
    const intervalMs = printerConnected ? PRINTER_CHECK_MS : PRINTER_RETRY_MS;
    const id = setInterval(() => {
      void checkLaser();
    }, intervalMs);
    return () => clearInterval(id);
  }, [printerConnected, checkLaser, settingsLoaded]);

  const goPrevDay = () => {
    setPlanDate((d) => dayjs(d).subtract(1, "day").format("YYYY-MM-DD"));
  };

  const goNextDay = () => {
    setPlanDate((d) => dayjs(d).add(1, "day").format("YYYY-MM-DD"));
  };

  const sendOne = (jo: JobOrderListItem) =>
    sendLaserBag2Job({
      itemId: jo.itemId,
      stockInLineId: jo.stockInLineId,
      itemCode: jo.itemCode,
      itemName: jo.itemName,
      jobOrderId: jo.id,
      jobOrderNo: jo.code,
      lotNo: jo.lotNo,
      source: "MANUAL",
    });

  const handleRowClick = async (jo: JobOrderListItem) => {
    if (sendingJobId !== null) return;

    if (!laserHost.trim()) {
      setErrorSnackbar({ open: true, message: "請在系統設定中填寫檸檬機(激光機) IP。" });
      return;
    }

    setSelectedId(jo.id);
    setSendingJobId(jo.id);
    try {
      let lastAck: string | undefined;
      let anyReceiveAck = false;
      for (let i = 0; i < LASER_SEND_COUNT; i++) {
        const r = await sendOne(jo);
        if (!r.success) {
          setErrorSnackbar({
            open: true,
            message: r.message || "檸檬機(激光機)未收到指令",
          });
          return;
        }
        if (r.printerAck) lastAck = r.printerAck;
        if (r.receiveAcknowledged) anyReceiveAck = true;
        if (i < LASER_SEND_COUNT - 1) {
          await delay(BETWEEN_SEND_MS);
        }
      }
      const ackHint =
        anyReceiveAck && lastAck
          ? `（印表機已回覆：${lastAck}）`
          : lastAck
            ? `（最後回覆：${lastAck}）`
            : "";
      setSuccessSignal(`已送出 ${LASER_SEND_COUNT} 次至檸檬機(激光機)${ackHint}`);
      await loadSystemSettings();
    } catch (e) {
      setErrorSnackbar({
        open: true,
        message: e instanceof Error ? e.message : "送出失敗",
      });
    } finally {
      setSendingJobId(null);
    }
  };

  const saveSettings = async () => {
    try {
      await patchSetting("LASER_PRINT.host", laserHost.trim());
      await patchSetting("LASER_PRINT.port", laserPort.trim() || "45678");
      await patchSetting("LASER_PRINT.itemCodes", laserItemCodes.trim());
      setSuccessSignal("設定已儲存");
      setSettingsOpen(false);
      void checkLaser();
      await loadSystemSettings();
      void loadJobOrders(false);
    } catch (e) {
      setErrorSnackbar({
        open: true,
        message: e instanceof Error ? e.message : "儲存失敗",
      });
    }
  };

  return (
    <Box sx={{ minHeight: "70vh", display: "flex", flexDirection: "column" }}>
      {successSignal && (
        <Alert severity="success" sx={{ mb: 2 }} onClose={() => setSuccessSignal(null)}>
          {successSignal}
        </Alert>
      )}
      {settingsLoaded && lastLaserReceive && (
        <Alert severity="info" sx={{ mb: 2 }}>
          <Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
            上次印表機已確認工單：{lastLaserReceive.jobOrderNo ?? "—"}　{formatHongKongDateTime(lastLaserReceive.sentAt)}
          </Typography>
        </Alert>
      )}

      <Paper sx={{ p: 2, mb: 2, backgroundColor: BG_TOP }}>
        <Stack direction="row" alignItems="center" justifyContent="space-between" flexWrap="wrap" gap={2}>
          <Stack direction="row" alignItems="center" spacing={2}>
            <Button variant="outlined" startIcon={<ChevronLeft />} onClick={goPrevDay} disabled={sendingJobId !== null}>
              前一天
            </Button>
            <TextField
              type="date"
              value={planDate}
              onChange={(e) => setPlanDate(e.target.value)}
              size="small"
              sx={{ width: 160 }}
              InputLabelProps={{ shrink: true }}
              disabled={sendingJobId !== null}
            />
            <Button variant="outlined" endIcon={<ChevronRight />} onClick={goNextDay} disabled={sendingJobId !== null}>
              後一天
            </Button>
          </Stack>
          <Stack direction="row" alignItems="center" spacing={2}>
            <Button
              variant="outlined"
              startIcon={<Settings />}
              onClick={() => setSettingsOpen(true)}
              disabled={sendingJobId !== null}
            >
              設定（系統）
            </Button>
            <Box
              sx={{
                px: 1.5,
                py: 0.75,
                borderRadius: 1,
                backgroundColor: printerConnected ? BG_STATUS_OK : BG_STATUS_ERROR,
                color: printerConnected ? FG_STATUS_OK : FG_STATUS_ERROR,
                fontWeight: 600,
                whiteSpace: "nowrap",
              }}
              title={printerMessage}
            >
              檸檬機(激光機)：
            </Box>
          </Stack>
        </Stack>
      </Paper>

      <Paper sx={{ flex: 1, overflow: "hidden", display: "flex", flexDirection: "column", backgroundColor: BG_LIST }}>
        {loading ? (
          <Box sx={{ display: "flex", justifyContent: "center", alignItems: "center", py: 8 }}>
            <CircularProgress />
          </Box>
        ) : error ? (
          <Box sx={{ py: 8, textAlign: "center" }}>
            <Typography color="error">{error}</Typography>
          </Box>
        ) : jobOrders.length === 0 ? (
          <Box sx={{ py: 8, textAlign: "center" }}>
            <Typography color="text.secondary">當日無工單</Typography>
          </Box>
        ) : (
          <Box sx={{ overflow: "auto", flex: 1, p: 2 }}>
            <Stack spacing={1}>
              {jobOrders.map((jo) => {
                const batch = getBatch(jo);
                const qtyStr = formatQty(jo.reqQty);
                const isSelected = selectedId === jo.id;
                const isSending = sendingJobId === jo.id;
                return (
                  <Paper
                    key={jo.id}
                    elevation={1}
                    sx={{
                      p: 2,
                      display: "flex",
                      alignItems: "flex-start",
                      gap: 2,
                      cursor: sendingJobId !== null ? "wait" : "pointer",
                      backgroundColor: isSelected ? BG_ROW_SELECTED : BG_ROW,
                      "&:hover": {
                        backgroundColor:
                          sendingJobId !== null
                            ? isSelected
                              ? BG_ROW_SELECTED
                              : BG_ROW
                            : isSelected
                              ? BG_ROW_SELECTED
                              : "#b8d4eb",
                      },
                      transition: "background-color 0.2s",
                      opacity: sendingJobId !== null && !isSending ? 0.65 : 1,
                    }}
                    onClick={() => void handleRowClick(jo)}
                  >
                    <Box sx={{ minWidth: 120, flexShrink: 0 }}>
                      <Typography variant="h6" sx={{ fontSize: "1.1rem" }}>
                        {batch}
                      </Typography>
                      {qtyStr !== "—" && (
                        <Typography variant="body2" color="text.secondary">
                          數量：{qtyStr}
                        </Typography>
                      )}
                    </Box>
                    <Box sx={{ minWidth: 140, flexShrink: 0 }}>
                      <Typography variant="h6" sx={{ fontSize: "1.1rem" }}>
                        {jo.code || "—"}
                      </Typography>
                    </Box>
                    <Box sx={{ minWidth: 140, flexShrink: 0 }}>
                      <Typography variant="h6" sx={{ fontSize: "1.35rem" }}>
                        {jo.itemCode || "—"}
                      </Typography>
                    </Box>
                    <Box sx={{ flex: 1, minWidth: 0 }}>
                      <Typography variant="h6" sx={{ fontSize: "1.35rem", wordBreak: "break-word" }}>
                        {jo.itemName || "—"}
                      </Typography>
                    </Box>
                    {isSending && <CircularProgress size={28} sx={{ alignSelf: "center", flexShrink: 0 }} />}
                  </Paper>
                );
              })}
            </Stack>
          </Box>
        )}
      </Paper>

      <Dialog open={settingsOpen} onClose={() => setSettingsOpen(false)} maxWidth="sm" fullWidth>
        <DialogTitle>檸檬機(激光機)（系統設定）</DialogTitle>
        <DialogContent>
          <Stack spacing={2} sx={{ mt: 1 }}>
            <Typography variant="body2" color="text.secondary">
              儲存後寫入資料庫，後端送出走此 IP／埠（預設 192.168.18.77:45678）。
            </Typography>
            <TextField
              label="IP"
              size="small"
              value={laserHost}
              onChange={(e) => setLaserHost(e.target.value)}
              fullWidth
            />
            <TextField
              label="Port"
              size="small"
              value={laserPort}
              onChange={(e) => setLaserPort(e.target.value)}
              fullWidth
            />
            <TextField
              label="列表品號（逗號分隔）"
              size="small"
              value={laserItemCodes}
              onChange={(e) => setLaserItemCodes(e.target.value)}
              fullWidth
              placeholder="PP1175"
              helperText="預設 PP1175；可輸入多個品號，例如 PP1175,AB999。留空則列表顯示當日全部包裝工單。"
            />
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setSettingsOpen(false)}>取消</Button>
          <Button variant="contained" onClick={() => void saveSettings()}>
            儲存
          </Button>
        </DialogActions>
      </Dialog>

      <Snackbar
        open={errorSnackbar.open}
        autoHideDuration={6000}
        onClose={() => setErrorSnackbar((s) => ({ ...s, open: false }))}
        message={errorSnackbar.message}
        anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
      />
    </Box>
  );
};

export default LaserPrintSearch;
