"use client";

import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import {
  Alert,
  Box,
  Button,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  FormControl,
  InputLabel,
  MenuItem,
  Select,
  Snackbar,
  Stack,
  TextField,
  Typography,
} from "@mui/material";
import { NEXT_PUBLIC_API_URL } from "@/config/api";
import { clientAuthFetch } from "@/app/utils/clientAuthFetch";

type ScanPayload = {
  itemId: number;
  stockInLineId: number;
};

type Printer = {
  id: number;
  name?: string;
  description?: string;
  ip?: string;
  port?: number;
  type?: string;
  brand?: string;
};

type QrCodeAnalysisResponse = {
  itemId: number;
  itemCode: string;
  itemName: string;
  scanned: {
    stockInLineId: number;
    lotNo: string;
    inventoryLotLineId: number;
    warehouseCode?: string | null;
    warehouseName?: string | null;
  };
  sameItemLots: Array<{
    lotNo: string;
    inventoryLotLineId: number;
    availableQty: number;
    uom: string;
    warehouseCode?: string | null;
    warehouseName?: string | null;
  }>;
};

export interface LotLabelPrintModalProps {
  open: boolean;
  onClose: () => void;
  /** 當由其他流程自動打開時，可帶入掃碼 payload 以便自動查詢 */
  initialPayload?: ScanPayload | null;
  /** 預設要自動選取的印表機名稱（完全匹配優先，其次為包含） */
  defaultPrinterName?: string;
  /** 隱藏「掃碼內容/查詢/清除」區塊（通常搭配 initialPayload 使用） */
  hideScanSection?: boolean;
  /** 額外提醒（顯示在最上方） */
  reminderText?: string;
  /** 額外標題（顯示在最上方，reminderText 之下） */
  statusTitleText?: string;
  /** 只顯示特定倉位前綴（例如 "2F-"） */
  warehouseCodePrefixFilter?: string;
  /** 不顯示觸發視窗的批號（analysis.scanned） */
  hideTriggeredLot?: boolean;
}

function safeParseScanPayload(raw: string): ScanPayload | null {
  try {
    const obj = JSON.parse(raw);
    const itemId = Number(obj?.itemId);
    const stockInLineId = Number(obj?.stockInLineId);
    if (!Number.isFinite(itemId) || !Number.isFinite(stockInLineId))
      return null;
    return { itemId, stockInLineId };
  } catch {
    return null;
  }
}

function formatPrinterLabel(p: Printer): string {
  const name = (p.name || "").trim();
  if (name) return name;
  const desc = (p.description || "").trim();
  if (desc) return desc;
  const code = (p as { code?: string }).code?.trim?.() ?? "";
  if (code) return code;
  return `#${p.id}`;
}

function isLabelPrinter(p: Printer): boolean {
  const s = `${p.name ?? ""} ${p.description ?? ""} ${
    (p as { code?: string }).code ?? ""
  } ${p.type ?? ""} ${p.brand ?? ""}`.toLowerCase();
  // Keep only "Label 機" printers; exclude A4 printers etc.
  return s.includes("label") && !s.includes("a4");
}

const LotLabelPrintModal: React.FC<LotLabelPrintModalProps> = ({
  open,
  onClose,
  initialPayload = null,
  defaultPrinterName,
  hideScanSection,
  reminderText,
  statusTitleText,
  warehouseCodePrefixFilter,
  hideTriggeredLot,
}) => {
  const scanInputRef = useRef<HTMLInputElement | null>(null);
  const [scanInput, setScanInput] = useState("");
  const [scanError, setScanError] = useState<string | null>(null);

  const [printers, setPrinters] = useState<Printer[]>([]);
  const [printersLoading, setPrintersLoading] = useState(false);
  const [selectedPrinterId, setSelectedPrinterId] = useState<number | "">("");

  const [analysisLoading, setAnalysisLoading] = useState(false);
  const [analysis, setAnalysis] = useState<QrCodeAnalysisResponse | null>(null);
  const [lastPayload, setLastPayload] = useState<ScanPayload | null>(null);

  const [printQty, setPrintQty] = useState(1);
  const [printingLotLineId, setPrintingLotLineId] = useState<number | null>(
    null,
  );

  const [snackbar, setSnackbar] = useState<{
    open: boolean;
    message: string;
    severity?: "success" | "info" | "error";
  }>({
    open: false,
    message: "",
    severity: "info",
  });

  const baseApi = useMemo(
    () => (NEXT_PUBLIC_API_URL ?? "").replace(/\/$/, ""),
    [],
  );

  const resetAll = useCallback(() => {
    setScanInput("");
    setScanError(null);
    setAnalysis(null);
    setPrintQty(1);
    setPrintingLotLineId(null);
  }, []);

  useEffect(() => {
    if (!open) return;
    resetAll();
    const t = setTimeout(() => scanInputRef.current?.focus(), 50);
    return () => clearTimeout(t);
  }, [open, resetAll]);

  const loadPrinters = useCallback(async () => {
    if (!baseApi) {
      setSnackbar({
        open: true,
        message: "NEXT_PUBLIC_API_URL 未設定，無法連線後端。",
        severity: "error",
      });
      return;
    }
    setPrintersLoading(true);
    try {
      const res = await clientAuthFetch(`${baseApi}/printers`, {
        method: "GET",
      });
      if (!res.ok) {
        const msg = await res.text().catch(() => "");
        throw new Error(msg || `HTTP ${res.status}`);
      }
      const data = (await res.json()) as Printer[];
      const list = Array.isArray(data) ? data : [];
      setPrinters(list.filter(isLabelPrinter));
    } catch (e) {
      setPrinters([]);
      setSnackbar({
        open: true,
        message: e instanceof Error ? e.message : "載入印表機清單失敗",
        severity: "error",
      });
    } finally {
      setPrintersLoading(false);
    }
  }, [baseApi]);

  useEffect(() => {
    if (!open) return;
    void loadPrinters();
  }, [open, loadPrinters]);

  const effectiveHideScanSection = hideScanSection ?? initialPayload != null;

  const pickDefaultPrinterId = useCallback(
    (list: Printer[]): number | null => {
      if (!defaultPrinterName) return null;
      const target = defaultPrinterName.trim().toLowerCase();
      if (!target) return null;
      const byExact = list.find(
        (p) => formatPrinterLabel(p).trim().toLowerCase() === target,
      );
      if (byExact) return byExact.id;
      const byIncludes = list.find((p) =>
        formatPrinterLabel(p).trim().toLowerCase().includes(target),
      );
      return byIncludes?.id ?? null;
    },
    [defaultPrinterName],
  );

  useEffect(() => {
    if (!open) return;
    if (selectedPrinterId !== "") return;
    if (printers.length === 0) return;
    const id = pickDefaultPrinterId(printers);
    if (id != null) setSelectedPrinterId(id);
  }, [open, printers, selectedPrinterId, pickDefaultPrinterId]);

  const analyzePayload = useCallback(
    async (payload: ScanPayload) => {
      if (!baseApi) {
        setScanError("NEXT_PUBLIC_API_URL 未設定，無法連線後端。");
        return;
      }

      setLastPayload(payload);
      setScanError(null);
      setAnalysisLoading(true);
      try {
        const res = await clientAuthFetch(
          `${baseApi}/inventoryLotLine/analyze-qr-code`,
          {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(payload),
          },
        );
        if (!res.ok) {
          const msg = await res.text().catch(() => "");
          throw new Error(msg || `分析失敗（HTTP ${res.status}）`);
        }
        const data = (await res.json()) as QrCodeAnalysisResponse;
        setAnalysis(data);
        setSnackbar({
          open: true,
          message: "已載入同品可用批號清單",
          severity: "success",
        });
      } catch (e) {
        setAnalysis(null);
        setScanError(e instanceof Error ? e.message : "分析失敗");
      } finally {
        setAnalysisLoading(false);
      }
    },
    [baseApi],
  );

  const handleAnalyze = useCallback(async () => {
    const raw = scanInput.trim();
    const payload = safeParseScanPayload(raw);
    if (!payload) {
      setScanError(
        '掃碼內容格式錯誤，需為 JSON，例如 {"itemId":16431,"stockInLineId":10381}',
      );
      setAnalysis(null);
      return;
    }
    await analyzePayload(payload);
  }, [scanInput, analyzePayload]);

  const handleRefreshLots = useCallback(async () => {
    const payload = lastPayload ?? safeParseScanPayload(scanInput.trim());
    if (!payload) {
      setSnackbar({
        open: true,
        message: "請先掃碼或查詢一次，才可刷新批號清單。",
        severity: "info",
      });
      return;
    }
    await analyzePayload(payload);
  }, [analyzePayload, lastPayload, scanInput]);

  useEffect(() => {
    if (!open) return;
    if (!initialPayload) return;
    setScanInput(JSON.stringify(initialPayload));
    void analyzePayload(initialPayload);
  }, [open, initialPayload, analyzePayload]);

  const availableLots = useMemo(() => {
    if (!analysis) return [];
    const list = (analysis.sameItemLots ?? []).filter(
      (x) => Number(x.availableQty) > 0 && !!String(x.lotNo || "").trim(),
    );
    const scannedLotLineId = analysis.scanned?.inventoryLotLineId;
    const scannedRow = scannedLotLineId
      ? list.find((x) => x.inventoryLotLineId === scannedLotLineId)
      : undefined;
    const scannedLot = scannedLotLineId
      ? {
          lotNo: analysis.scanned.lotNo,
          inventoryLotLineId: scannedLotLineId,
          availableQty: (scannedRow?.availableQty ?? 0) as number,
          uom: (scannedRow?.uom ?? "") as string,
          warehouseCode:
            analysis.scanned.warehouseCode ?? scannedRow?.warehouseCode,
          warehouseName:
            analysis.scanned.warehouseName ?? scannedRow?.warehouseName,
          _scanned: true as const,
        }
      : null;

    const merged = [
      ...(!hideTriggeredLot && scannedLot ? [scannedLot] : []),
      ...list
        .filter((x) => x.inventoryLotLineId !== scannedLotLineId)
        .map((x) => ({ ...x, _scanned: false as const })),
    ];

    return merged;
  }, [analysis, hideTriggeredLot]);

  const filteredLots = useMemo(() => {
    const prefix = String(warehouseCodePrefixFilter ?? "").trim();
    if (!prefix) return availableLots;
    return availableLots.filter((lot) =>
      String(lot.warehouseCode ?? "").startsWith(prefix),
    );
  }, [availableLots, warehouseCodePrefixFilter]);

  const selectedPrinter = useMemo(() => {
    if (selectedPrinterId === "") return null;
    return printers.find((p) => p.id === selectedPrinterId) ?? null;
  }, [printers, selectedPrinterId]);

  const canPrint =
    !!analysis && selectedPrinterId !== "" && printQty >= 1 && !analysisLoading;

  const handlePrintOne = useCallback(
    async (inventoryLotLineId: number, lotNo: string) => {
      if (!baseApi) {
        setSnackbar({
          open: true,
          message: "NEXT_PUBLIC_API_URL 未設定，無法連線後端。",
          severity: "error",
        });
        return;
      }
      if (selectedPrinterId === "") {
        setSnackbar({
          open: true,
          message: "請先選擇印表機",
          severity: "error",
        });
        return;
      }
      if (printQty < 1 || !Number.isFinite(printQty)) {
        setSnackbar({
          open: true,
          message: "列印張數需為大於等於 1 的整數",
          severity: "error",
        });
        return;
      }

      setPrintingLotLineId(inventoryLotLineId);
      try {
        const sp = new URLSearchParams();
        sp.set("inventoryLotLineId", String(inventoryLotLineId));
        sp.set("printerId", String(selectedPrinterId));
        sp.set("printQty", String(Math.floor(printQty)));

        const url = `${baseApi}/inventoryLotLine/print-label?${sp.toString()}`;
        const res = await clientAuthFetch(url, { method: "GET" });
        if (!res.ok) {
          const msg = await res.text().catch(() => "");
          throw new Error(msg || `列印失敗（HTTP ${res.status}）`);
        }
        setSnackbar({
          open: true,
          message: `已送出列印：Lot ${lotNo}`,
          severity: "success",
        });
      } catch (e) {
        setSnackbar({
          open: true,
          message: e instanceof Error ? e.message : "列印失敗",
          severity: "error",
        });
      } finally {
        setPrintingLotLineId(null);
      }
    },
    [baseApi, selectedPrinterId, printQty],
  );

  return (
    <Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
      <DialogTitle>批號標籤列印</DialogTitle>
      <DialogContent>
        <Stack spacing={2} sx={{ mt: 1 }}>
          {statusTitleText ? (
            <Typography
              variant="h6"
              sx={{ fontWeight: 800, color: "error.main" }}
            >
              {statusTitleText}
            </Typography>
          ) : null}
          {reminderText ? (
            <Alert severity="warning">{reminderText}</Alert>
          ) : null}
          {effectiveHideScanSection ? null : (
            <>
              <Alert severity="info">
                請掃描條碼（JSON 格式），例如{" "}
                <code>{'{"itemId":16431,"stockInLineId":10381'}</code>。
              </Alert>

              <Stack
                direction={{ xs: "column", md: "row" }}
                spacing={2}
                alignItems={{ xs: "stretch", md: "center" }}
              >
                <TextField
                  inputRef={scanInputRef}
                  label="掃碼內容"
                  value={scanInput}
                  onChange={(e) => setScanInput(e.target.value)}
                  fullWidth
                  size="small"
                  error={!!scanError}
                  helperText={scanError || "掃描後按 Enter 或點「查詢」"}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") {
                      e.preventDefault();
                      void handleAnalyze();
                    }
                  }}
                  disabled={analysisLoading}
                />
                <Button
                  variant="contained"
                  onClick={() => void handleAnalyze()}
                  disabled={analysisLoading || !scanInput.trim()}
                >
                  {analysisLoading ? <CircularProgress size={18} /> : "查詢"}
                </Button>
                <Button
                  variant="outlined"
                  onClick={() => {
                    resetAll();
                    scanInputRef.current?.focus();
                  }}
                  disabled={analysisLoading}
                >
                  清除
                </Button>
              </Stack>
            </>
          )}

          <Stack
            direction={{ xs: "column", md: "row" }}
            spacing={2}
            alignItems={{ xs: "stretch", md: "center" }}
          >
            <FormControl
              size="small"
              sx={{ minWidth: 260 }}
              disabled={printersLoading}
            >
              <InputLabel>印表機</InputLabel>
              <Select
                label="印表機"
                value={selectedPrinterId}
                onChange={(e) =>
                  setSelectedPrinterId((e.target.value as number) ?? "")
                }
              >
                <MenuItem value="">
                  <em>{printersLoading ? "載入中..." : "請選擇"}</em>
                </MenuItem>
                {printers.map((p) => (
                  <MenuItem key={p.id} value={p.id}>
                    {formatPrinterLabel(p)}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>

            <TextField
              label="列印張數"
              size="small"
              type="number"
              inputProps={{ min: 1, step: 1 }}
              value={printQty}
              onChange={(e) => setPrintQty(Number(e.target.value))}
              sx={{ width: 140 }}
              disabled={analysisLoading}
            />

            <Button
              variant="outlined"
              onClick={() => void handleRefreshLots()}
              disabled={analysisLoading}
            >
              {analysisLoading ? (
                <CircularProgress size={18} />
              ) : (
                "刷新批號清單"
              )}
            </Button>

            {selectedPrinter && (
              <Typography
                variant="body2"
                color="text.secondary"
                sx={{ ml: { md: "auto" } }}
              >
                已選：{formatPrinterLabel(selectedPrinter)}
              </Typography>
            )}
          </Stack>

          {analysis && (
            <Box>
              <Typography variant="subtitle1" sx={{ fontWeight: 700, mb: 1 }}>
                品號：{analysis.itemCode}　{analysis.itemName}
              </Typography>

              {filteredLots.length === 0 ? (
                <Alert severity="warning">
                  找不到該樓層有可用批號（availableQty &gt; 0）。
                </Alert>
              ) : (
                <Stack spacing={1}>
                  {filteredLots.map((lot) => {
                    const isPrinting =
                      printingLotLineId === lot.inventoryLotLineId;
                    const loc = String(lot.warehouseCode ?? "").trim();
                    return (
                      <Box
                        key={lot.inventoryLotLineId}
                        sx={{
                          p: 1.25,
                          borderRadius: 1,
                          border: "1px solid",
                          borderColor: "divider",
                          display: "flex",
                          alignItems: "center",
                          gap: 2,
                          backgroundColor: lot._scanned
                            ? "rgba(25, 118, 210, 0.08)"
                            : "transparent",
                        }}
                      >
                        <Box sx={{ minWidth: 220 }}>
                          <Typography
                            variant="body1"
                            sx={{ fontWeight: lot._scanned ? 800 : 600 }}
                          >
                            Lot：{lot.lotNo}
                            {lot._scanned ? "（已掃）" : ""}
                          </Typography>
                          <Typography variant="body2" color="text.secondary">
                            位置：{loc || "—"}
                          </Typography>
                          <Typography variant="body2" color="text.secondary">
                            可用量：{Number(lot.availableQty).toLocaleString()}{" "}
                            單位：{lot.uom || ""}
                          </Typography>
                        </Box>
                        <Box sx={{ ml: "auto" }}>
                          <Button
                            variant="contained"
                            disabled={!canPrint || isPrinting}
                            onClick={() =>
                              void handlePrintOne(
                                lot.inventoryLotLineId,
                                lot.lotNo,
                              )
                            }
                          >
                            {isPrinting ? (
                              <CircularProgress size={18} />
                            ) : (
                              "列印標籤"
                            )}
                          </Button>
                        </Box>
                      </Box>
                    );
                  })}
                </Stack>
              )}
            </Box>
          )}

          {!analysis && !analysisLoading && (
            <Typography variant="body2" color="text.secondary">
              掃碼後會用 `/inventoryLotLine/analyze-qr-code`
              查詢同品批號，列印則呼叫
              `/inventoryLotLine/print-label`（需先選印表機）。
            </Typography>
          )}
        </Stack>
      </DialogContent>
      <DialogActions>
        <Button onClick={onClose}>關閉</Button>
      </DialogActions>

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

export default LotLabelPrintModal;
