"use client";

import React, { useCallback, useEffect, useState } from "react";
import {
  Box,
  Button,
  FormControl,
  InputLabel,
  MenuItem,
  Select,
  Stack,
  Typography,
  Paper,
  CircularProgress,
  SelectChangeEvent,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  TextField,
  Snackbar,
} 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 Print from "@mui/icons-material/Print";
import Download from "@mui/icons-material/Download";
import {
  checkPrinterStatus,
  downloadOnPackQrZip,
  downloadOnPackTextQrZip,
  fetchJobOrders,
  JobOrderListItem,
} from "@/app/api/bagPrint/actions";
import dayjs from "dayjs";
import { NEXT_PUBLIC_API_URL } from "@/config/api";
import { clientAuthFetch } from "@/app/utils/clientAuthFetch";

// Light blue theme (matching Python Bag1)
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 PRINTER_OPTIONS = [
  { value: "dataflex", label: "打袋機 DataFlex" },
  { value: "laser", label: "激光機" },
];

const REFRESH_MS = 60 * 1000;
const PRINTER_CHECK_MS = 60 * 1000;
const PRINTER_RETRY_MS = 30 * 1000;
const SETTINGS_KEY = "bagPrint_settings";

const DEFAULT_SETTINGS = {
  dabag_ip: "",
  dabag_port: "3008",
  laser_ip: "192.168.17.10",
  laser_port: "45678",
};

function loadSettings(): typeof DEFAULT_SETTINGS {
  if (typeof window === "undefined") return DEFAULT_SETTINGS;
  try {
    const s = localStorage.getItem(SETTINGS_KEY);
    if (s) return { ...DEFAULT_SETTINGS, ...JSON.parse(s) };
  } catch {}
  return DEFAULT_SETTINGS;
}

function saveSettings(s: typeof DEFAULT_SETTINGS) {
  if (typeof window === "undefined") return;
  try {
    localStorage.setItem(SETTINGS_KEY, JSON.stringify(s));
  } catch {}
}

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() || "—";
}

const BagPrintSearch: 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 [printer, setPrinter] = useState<string>("dataflex");
  const [selectedId, setSelectedId] = useState<number | null>(null);
  const [printDialogOpen, setPrintDialogOpen] = useState(false);
  const [printTarget, setPrintTarget] = useState<JobOrderListItem | null>(null);
  const [printCount, setPrintCount] = useState(0);
  const [printContinuous, setPrintContinuous] = useState(false);
  const [printing, setPrinting] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [snackbar, setSnackbar] = useState<{ open: boolean; message: string; severity?: "success" | "info" | "error" }>({ open: false, message: "" });
  const [settings, setSettings] = useState(DEFAULT_SETTINGS);
  const [printerConnected, setPrinterConnected] = useState(false);
  const [printerMessage, setPrinterMessage] = useState("列印機未連接");
  const [downloadingOnPack, setDownloadingOnPack] = useState(false);
  const [downloadingOnPackText, setDownloadingOnPackText] = useState(false);

  useEffect(() => {
    setSettings(loadSettings());
  }, []);

  const loadJobOrders = useCallback(async (fromUserChange = false) => {
    setLoading(true);
    setError(null);
    try {
      const data = await fetchJobOrders(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(() => {
    loadJobOrders(true);
  }, [planDate]);

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

  const checkCurrentPrinter = useCallback(async () => {
    try {
      const request =
        printer === "dataflex"
          ? {
              printerType: "dataflex" as const,
              printerIp: settings.dabag_ip,
              printerPort: Number(settings.dabag_port || 3008),
            }
          : {
              printerType: "laser" as const,
              printerIp: settings.laser_ip,
              printerPort: Number(settings.laser_port || 45678),
            };

      const result = await checkPrinterStatus(request);
      setPrinterConnected(result.connected);
      setPrinterMessage(result.message);
    } catch (e) {
      setPrinterConnected(false);
      setPrinterMessage(e instanceof Error ? e.message : "列印機狀態檢查失敗");
    }
  }, [printer, settings]);

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

  useEffect(() => {
    const intervalMs = printerConnected ? PRINTER_CHECK_MS : PRINTER_RETRY_MS;
    const id = setInterval(() => {
      checkCurrentPrinter();
    }, intervalMs);

    return () => clearInterval(id);
  }, [printerConnected, checkCurrentPrinter]);

  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 handlePrinterChange = (e: SelectChangeEvent<string>) => {
    setPrinter(e.target.value);
  };

  const handleRowClick = (jo: JobOrderListItem) => {
    setSelectedId(jo.id);
    const batch = getBatch(jo);
    const itemCode = jo.itemCode || "—";
    const itemName = jo.itemName || "—";
    setSnackbar({ open: true, message: `已點選：批次 ${batch} 品號 ${itemCode} ${itemName}`, severity: "info" });

    // Align with Bag2.py "click row -> ask bag count -> print" for DataFlex.
    if (printer === "dataflex") {
      setPrintTarget(jo);
      setPrintCount(0);
      setPrintContinuous(false);
      setPrintDialogOpen(true);
    }
  };

  const confirmPrintDataFlex = async () => {
    if (!printTarget) return;
    if (printer !== "dataflex") {
      setSnackbar({ open: true, message: "此頁目前只支援打袋機 DataFlex 列印", severity: "error" });
      return;
    }

    if (!printContinuous && printCount < 1) {
      setSnackbar({ open: true, message: "請先按 +50、+10、+5 或 +1 選擇數量。", severity: "error" });
      return;
    }

    const qty = printContinuous ? -1 : printCount;
    const printerIp = settings.dabag_ip;
    const printerPort = Number(settings.dabag_port || 3008);

    if (!printerIp) {
      setSnackbar({ open: true, message: "請先在設定中填寫打袋機 DataFlex 的 IP。", severity: "error" });
      return;
    }

    setPrinting(true);
    try {
      const resp = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/plastic/print-dataflex`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          itemCode: printTarget.itemCode || "—",
          itemName: printTarget.itemName || "—",
          lotNo: printTarget.lotNo || "—",
          // DataFlex zpl (Bag2.py) only needs itemId + stockInLineId for QR payload (optional).
          itemId: printTarget.itemId,
          stockInLineId: printTarget.stockInLineId,
          printerIp,
          printerPort,
          printQty: qty,
        }),
      });

      if (resp.status === 401 || resp.status === 403) return;

      if (!resp.ok) {
        const msg = await resp.text().catch(() => "");
        setSnackbar({
          open: true,
          message: `DataFlex 列印失敗（狀態碼 ${resp.status}）。${msg ? msg.slice(0, 120) : ""}`,
          severity: "error",
        });
        return;
      }

      const batch = getBatch(printTarget);
      const printedText = qty === -1 ? "連續 (C)" : `${qty}`;
      setSnackbar({ open: true, message: `已送出列印：批次 ${batch} x ${printedText}`, severity: "success" });
      setPrintDialogOpen(false);
    } catch (e) {
      setSnackbar({ open: true, message: e instanceof Error ? e.message : "DataFlex 列印失敗", severity: "error" });
    } finally {
      setPrinting(false);
    }
  };

  const handleDownloadOnPackQr = async () => {
    const onPackJobOrders = jobOrders
      .map((jobOrder) => ({
        jobOrderId: jobOrder.id,
        itemCode: jobOrder.itemCode?.trim() || "",
      }))
      .filter((jobOrder) => jobOrder.itemCode.length > 0);

    if (onPackJobOrders.length === 0) {
      setSnackbar({ open: true, message: "當日沒有可下載的 job order", severity: "error" });
      return;
    }

    setDownloadingOnPack(true);
    try {
      const blob = await downloadOnPackQrZip({
        jobOrders: onPackJobOrders,
      });

      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.setAttribute("download", `onpack_qr_${planDate}.zip`);
      document.body.appendChild(link);
      link.click();
      link.remove();
      window.URL.revokeObjectURL(url);

      setSnackbar({ open: true, message: "OnPack QR code ZIP 已下載", severity: "success" });
    } catch (e) {
      setSnackbar({
        open: true,
        message: e instanceof Error ? e.message : "下載 OnPack QR code 失敗",
        severity: "error",
      });
    } finally {
      setDownloadingOnPack(false);
    }
  };

  const handleDownloadOnPackTextQr = async () => {
    const onPackJobOrders = jobOrders
      .map((jobOrder) => ({
        jobOrderId: jobOrder.id,
        itemCode: jobOrder.itemCode?.trim() || "",
      }))
      .filter((jobOrder) => jobOrder.itemCode.length > 0);

    if (onPackJobOrders.length === 0) {
      setSnackbar({ open: true, message: "當日沒有可下載的 job order", severity: "error" });
      return;
    }

    setDownloadingOnPackText(true);
    try {
      const blob = await downloadOnPackTextQrZip({
        jobOrders: onPackJobOrders,
      });

      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.setAttribute("download", `onpack2023_lemon_qr_${planDate}.zip`);
      document.body.appendChild(link);
      link.click();
      link.remove();
      window.URL.revokeObjectURL(url);

      setSnackbar({ open: true, message: "OnPack2023檸檬機 ZIP 已下載", severity: "success" });
    } catch (e) {
      setSnackbar({
        open: true,
        message: e instanceof Error ? e.message : "下載 OnPack2023檸檬機 失敗",
        severity: "error",
      });
    } finally {
      setDownloadingOnPackText(false);
    }
  };

  return (
    <Box sx={{ minHeight: "70vh", display: "flex", flexDirection: "column" }}>
      {/* Top: date nav + printer + settings */}
      <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}>
              前一天
            </Button>
            <TextField
              type="date"
              value={planDate}
              onChange={(e) => setPlanDate(e.target.value)}
              size="small"
              sx={{ width: 160 }}
              InputLabelProps={{ shrink: true }}
            />
            <Button variant="outlined" endIcon={<ChevronRight />} onClick={goNextDay}>
              後一天
            </Button>
          </Stack>
          <Stack direction="row" alignItems="center" spacing={2}>
            <Button variant="outlined" startIcon={<Settings />} onClick={() => setSettingsOpen(true)}>
              設定
            </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>
            <FormControl size="small" sx={{ minWidth: 180 }}>
              <InputLabel>列印機</InputLabel>
              <Select value={printer} label="列印機" onChange={handlePrinterChange}>
                {PRINTER_OPTIONS.map((opt) => (
                  <MenuItem key={opt.value} value={opt.value}>
                    {opt.label}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
          </Stack>
        </Stack>
        <Typography variant="body2" sx={{ mt: 1, color: "text.secondary" }}>
          {printerMessage}
        </Typography>
        <Stack direction="row" sx={{ mt: 2 }} spacing={2} flexWrap="wrap" useFlexGap>
          <Button
            variant="contained"
            startIcon={<Download />}
            onClick={handleDownloadOnPackQr}
            disabled={loading || downloadingOnPack || downloadingOnPackText || jobOrders.length === 0}
          >
            {downloadingOnPack ? "下載中..." : "下載 OnPack 汁水機 QR code"}
          </Button>
          <Button
            variant="contained"
            color="secondary"
            startIcon={<Download />}
            onClick={handleDownloadOnPackTextQr}
            disabled={loading || downloadingOnPack || downloadingOnPackText || jobOrders.length === 0}
          >
            {downloadingOnPackText ? "下載中..." : "下載 OnPack2023檸檬機"}
          </Button>
        </Stack>
      </Paper>

      {/* Job orders list */}
      <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>
        ) : 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;
                return (
                  <Paper
                    key={jo.id}
                    elevation={1}
                    sx={{
                      p: 2,
                      display: "flex",
                      alignItems: "flex-start",
                      gap: 2,
                      cursor: "pointer",
                      backgroundColor: isSelected ? BG_ROW_SELECTED : BG_ROW,
                      "&:hover": { backgroundColor: isSelected ? BG_ROW_SELECTED : "#b8d4eb" },
                      transition: "background-color 0.2s",
                    }}
                    onClick={() => 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>
                    <Button
                      size="small"
                      variant="contained"
                      startIcon={<Print />}
                      onClick={(e) => {
                        e.stopPropagation();
                        handleRowClick(jo);
                      }}
                    >
                      列印
                    </Button>
                  </Paper>
                );
              })}
            </Stack>
          </Box>
        )}
      </Paper>

      {/* Print count dialog (DataFlex) */}
      <Dialog open={printDialogOpen} onClose={() => (printing ? null : setPrintDialogOpen(false))} maxWidth="xs" fullWidth>
        <DialogTitle>打袋機 DataFlex 列印數量</DialogTitle>
        <DialogContent>
          <Stack spacing={2} sx={{ mt: 1 }}>
            <Typography variant="body1" sx={{ fontWeight: 700 }}>
              列印多少個袋？
            </Typography>
            <Typography variant="body2" color="text.secondary">
              {printContinuous ? "連續 (C)" : `數量： ${printCount}`}
            </Typography>
            <Stack direction="row" spacing={1} justifyContent="center" flexWrap="wrap">
              <Button
                size="small"
                variant="contained"
                onClick={() => {
                  setPrintContinuous(false);
                  setPrintCount((c) => c + 50);
                }}
                disabled={printing}
              >
                +50
              </Button>
              <Button
                size="small"
                variant="contained"
                onClick={() => {
                  setPrintContinuous(false);
                  setPrintCount((c) => c + 10);
                }}
                disabled={printing}
              >
                +10
              </Button>
              <Button
                size="small"
                variant="contained"
                onClick={() => {
                  setPrintContinuous(false);
                  setPrintCount((c) => c + 5);
                }}
                disabled={printing}
              >
                +5
              </Button>
              <Button
                size="small"
                variant="contained"
                onClick={() => {
                  setPrintContinuous(false);
                  setPrintCount((c) => c + 1);
                }}
                disabled={printing}
              >
                +1
              </Button>
              <Button
                size="small"
                variant={printContinuous ? "contained" : "outlined"}
                onClick={() => {
                  setPrintContinuous(true);
                }}
                disabled={printing}
              >
                連續 (C)
              </Button>
            </Stack>
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setPrintDialogOpen(false)} disabled={printing}>
            取消
          </Button>
          <Button variant="contained" onClick={() => void confirmPrintDataFlex()} disabled={printing}>
            {printing ? <CircularProgress size={16} /> : "確認送出"}
          </Button>
        </DialogActions>
      </Dialog>

      {/* Settings dialog */}
      <Dialog open={settingsOpen} onClose={() => setSettingsOpen(false)} maxWidth="sm" fullWidth>
        <DialogTitle>設定</DialogTitle>
        <DialogContent>
          <Stack spacing={2} sx={{ mt: 1 }}>
            <Typography variant="subtitle2" color="primary">
              打袋機 DataFlex
            </Typography>
            <TextField
              label="IP"
              size="small"
              value={settings.dabag_ip}
              onChange={(e) => setSettings((s) => ({ ...s, dabag_ip: e.target.value }))}
              fullWidth
            />
            <TextField
              label="Port"
              size="small"
              value={settings.dabag_port}
              onChange={(e) => setSettings((s) => ({ ...s, dabag_port: e.target.value }))}
              fullWidth
            />
            <Typography variant="subtitle2" color="primary">
              激光機
            </Typography>
            <TextField
              label="IP"
              size="small"
              value={settings.laser_ip}
              onChange={(e) => setSettings((s) => ({ ...s, laser_ip: e.target.value }))}
              fullWidth
            />
            <TextField
              label="Port"
              size="small"
              value={settings.laser_port}
              onChange={(e) => setSettings((s) => ({ ...s, laser_port: e.target.value }))}
              fullWidth
            />
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setSettingsOpen(false)}>取消</Button>
          <Button
            variant="contained"
            onClick={() => {
              saveSettings(settings);
              setSnackbar({ open: true, message: "設定已儲存", severity: "success" });
              setSettingsOpen(false);
              checkCurrentPrinter();
            }}
          >
            儲存
          </Button>
        </DialogActions>
      </Dialog>

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

export default BagPrintSearch;
