"use client";

/**
 * Workbench copy of `LotLabelPrintModal`: same label-print flow, plus optional
 * 「掃碼提貨」 per listed lot row (parent calls `workbenchScanPick` with `inventoryLotLineId`).
 */

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 {
  analyzeWorkbenchQrCode,
  fetchWorkbenchAvailableLotsByItem,
  fetchWorkbenchPrinters,
  printWorkbenchLotLabel,
} from "@/app/api/doworkbench/actions";
import { QRCodeSVG } from "qrcode.react";

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;
    uom?: string | null;
    uomId?: number | null;
  } | null;
  sameItemLots: Array<{
    lotNo: string;
    inventoryLotLineId: number;
    stockInLineId?: number | null;
    availableQty: number;
    uom: string;
    uomId?: number | null;
    warehouseCode?: string | null;
    warehouseName?: string | null;
  }>;
};

export interface WorkbenchLotLabelPrintModalProps {
  open: boolean;
  onClose: () => void;
  initialPayload?: ScanPayload | null;
  initialItemId?: number | null;
  defaultPrinterName?: string;
  hideScanSection?: boolean;
  reminderText?: string;
  statusTitleText?: string;
  /** 與 statusTitleText 搭配；預設 error（舊版固定紅字） */
  statusTitleSeverity?: "success" | "warning" | "error";
  warehouseCodePrefixFilter?: string;
  /**
   * When true, omit the API 「scanned」 lot from the merged list (legacy FG-style).
   * Workbench should leave false so the current row’s lot appears for label print / scan-pick.
   */
  hideTriggeredLot?: boolean;
  /** 提貨台表格列上的可用量／單位（API 的 sameItemLots 不含掃描行，需補上才能顯示「目前這筆」） */
  triggerLotAvailableQty?: number | null;
  triggerLotUom?: string | null;
  /** POL UomConversion id — workbench lot list only returns matching UOM */
  expectedUomId?: number | null;
  /** 此出庫行已掃碼／已完成時為 true，停用所有「掃碼提貨」（仍可列印標籤） */
  disableScanPick?: boolean;
  /**
   * When set, each lot row shows 「掃碼提貨」. Parent should call `workbenchScanPick`
   * with `inventoryLotLineId` and throw on failure.
   */
  onWorkbenchScanPick?: (args: {
    inventoryLotLineId: number;
    lotNo: string;
    qty?: number;
  }) => Promise<void>;
  /** Global submit qty shared with outer "Qty will submit". */
  submitQty?: number | null;
  onSubmitQtyChange?: (qty: number) => void;
}

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();
  return s.includes("label") && !s.includes("a4");
}

/** FP-MTMS Version Checklist | Functions Ref. No. 30 | v1.0.1 | 2026-07-22 */
const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> = ({
  open,
  onClose,
  initialPayload = null,
  initialItemId = null,
  defaultPrinterName,
  hideScanSection,
  reminderText,
  statusTitleText,
  statusTitleSeverity = "error",
  warehouseCodePrefixFilter,
  hideTriggeredLot = false,
  triggerLotAvailableQty = null,
  triggerLotUom = null,
  expectedUomId = null,
  disableScanPick = false,
  onWorkbenchScanPick,
  submitQty = null,
  onSubmitQtyChange,
}) => {
  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 [lastItemId, setLastItemId] = useState<number | null>(null);

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

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

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

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

  const loadPrinters = useCallback(async () => {
    setPrintersLoading(true);
    try {
      const data = (await fetchWorkbenchPrinters()) 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);
    }
  }, []);

  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 resolveExpectedUomId = useCallback((): number | null => {
    const n = Number(expectedUomId);
    return Number.isFinite(n) && n > 0 ? n : null;
  }, [expectedUomId]);

  const analyzePayload = useCallback(
    async (payload: ScanPayload) => {
      setLastPayload(payload);
      setScanError(null);
      setAnalysisLoading(true);
      try {
        const uomId = resolveExpectedUomId();
        const data = (await analyzeWorkbenchQrCode({
          ...payload,
          ...(uomId != null ? { uomId } : {}),
        })) as QrCodeAnalysisResponse;
        setAnalysis(data);
        setSnackbar({
          open: true,
          message: "已載入同品可用批號清單",
          severity: "success",
        });
      } catch (e) {
        setAnalysis(null);
        setScanError(e instanceof Error ? e.message : "分析失敗");
      } finally {
        setAnalysisLoading(false);
      }
    },
    [resolveExpectedUomId],
  );

  const analyzeByItem = useCallback(
    async (itemId: number) => {
      if (!Number.isFinite(itemId) || itemId <= 0) {
        setScanError("無效 itemId，無法載入批號清單。");
        return;
      }
      setLastItemId(itemId);
      setScanError(null);
      setAnalysisLoading(true);
      try {
        const uomId = resolveExpectedUomId();
        const data = (await fetchWorkbenchAvailableLotsByItem(
          itemId,
          uomId,
        )) as {
          itemId: number;
          itemCode: string;
          itemName: string;
          sameItemLots: QrCodeAnalysisResponse["sameItemLots"];
        };
        setAnalysis({
          itemId: data.itemId,
          itemCode: data.itemCode,
          itemName: data.itemName,
          scanned: null,
          sameItemLots: data.sameItemLots ?? [],
        });
        setSnackbar({
          open: true,
          message: "已載入同品可用批號清單",
          severity: "success",
        });
      } catch (e) {
        setAnalysis(null);
        setScanError(e instanceof Error ? e.message : "分析失敗");
      } finally {
        setAnalysisLoading(false);
      }
    },
    [resolveExpectedUomId],
  );

  const handleAnalyze = useCallback(async () => {
    const raw = scanInput.trim();
    const payload = safeParseScanPayload(raw);
    if (!payload) {
      setScanError(
        '掃碼內容格式錯誤，請重新掃碼',
      );
      setAnalysis(null);
      return;
    }
    await analyzePayload(payload);
  }, [scanInput, analyzePayload]);

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

  useEffect(() => {
    if (!open) return;
    if (initialPayload) {
      setScanInput(JSON.stringify(initialPayload));
      void analyzePayload(initialPayload);
      return;
    }
    if (Number.isFinite(Number(initialItemId)) && Number(initialItemId) > 0) {
      void analyzeByItem(Number(initialItemId));
    }
  }, [open, initialPayload, initialItemId, analyzePayload, analyzeByItem]);

  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 tableQty = Number(triggerLotAvailableQty);
    const fromTable =
      Number.isFinite(tableQty) && tableQty >= 0 ? tableQty : 0;
    const fromApi = Number(scannedRow?.availableQty ?? 0);
    const scanned = analysis.scanned;
    const expectUom = Number(expectedUomId);
    const hasExpectUom = Number.isFinite(expectUom) && expectUom > 0;
    const scannedUomId = Number(scanned?.uomId ?? scannedRow?.uomId ?? 0);
    const scannedUomOk =
      !hasExpectUom ||
      !Number.isFinite(scannedUomId) ||
      scannedUomId <= 0 ||
      scannedUomId === expectUom;
    const scannedLot =
      scannedLotLineId && scannedUomOk
        ? {
            lotNo: scanned?.lotNo ?? "",
            inventoryLotLineId: scannedLotLineId,
            stockInLineId: Number(scanned?.stockInLineId ?? 0) || null,
            availableQty: Math.max(fromApi, fromTable) as number,
            uom: (scanned?.uom ?? scannedRow?.uom ?? triggerLotUom ?? "") as string,
            uomId: scannedUomId > 0 ? scannedUomId : null,
            warehouseCode:
              scanned?.warehouseCode ?? scannedRow?.warehouseCode,
            warehouseName:
              scanned?.warehouseName ?? scannedRow?.warehouseName,
            _scanned: true as const,
          }
        : null;

    const merged = [
      ...(!hideTriggeredLot && scannedLot ? [scannedLot] : []),
      ...list
        .filter((x) => x.inventoryLotLineId !== scannedLotLineId)
        .filter((x) => {
          if (!hasExpectUom) return true;
          const id = Number(x.uomId);
          return !Number.isFinite(id) || id <= 0 || id === expectUom;
        })
        .map((x) => ({ ...x, _scanned: false as const })),
    ];

    return merged;
  }, [
    analysis,
    hideTriggeredLot,
    triggerLotAvailableQty,
    triggerLotUom,
    expectedUomId,
  ]);

  const filteredLots = useMemo(() => {
    const prefix = String(warehouseCodePrefixFilter ?? "").trim();
    if (!prefix) return availableLots;
    return availableLots.filter((lot) => {
      // 使用者從本列開啟視窗：即使 API 未帶 warehouseCode，仍應顯示目前這筆批號
      if (lot._scanned) return true;
      return 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 (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 {
        await printWorkbenchLotLabel({
          inventoryLotLineId,
          printerId: selectedPrinterId,
          printQty: Math.floor(printQty),
        });
        setSnackbar({
          open: true,
          message: `已送出列印：Lot ${lotNo}`,
          severity: "success",
        });
      } catch (e) {
        setSnackbar({
          open: true,
          message: e instanceof Error ? e.message : "列印失敗",
          severity: "error",
        });
      } finally {
        setPrintingLotLineId(null);
      }
    },
    [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:
                  statusTitleSeverity === "success"
                    ? "success.main"
                    : statusTitleSeverity === "warning"
                      ? "warning.main"
                      : "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}
            />

            {onWorkbenchScanPick ? (
              <TextField
                label="提交數量"
                size="small"
                type="number"
                inputProps={{ min: 0, step: 1 }}
                value={
                  Number.isFinite(Number(submitQty)) ? Number(submitQty) : 0
                }
                onChange={(e) => {
                  const n = Number(e.target.value);
                  if (!Number.isFinite(n) || n < 0) return;
                  onSubmitQtyChange?.(n);
                }}
                sx={{ width: 140 }}
                disabled={analysisLoading}
              />
            ) : null}

            <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();
                    const canShowLotQr =
                      !!onWorkbenchScanPick &&
                      !!analysis &&
                      !analysisLoading &&
                      !disableScanPick;
                    const lotQrPayload =
                      Number.isFinite(Number(analysis?.itemId)) &&
                      Number.isFinite(Number(lot.stockInLineId))
                        ? {
                            itemId: Number(analysis?.itemId),
                            stockInLineId: Number(lot.stockInLineId),
                          }
                        : null;
                    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>
                        <Stack
                          direction="row"
                          spacing={1}
                          sx={{ ml: "auto" }}
                          flexWrap="wrap"
                          useFlexGap
                        >
                          <Button
                            variant="contained"
                            disabled={!canPrint || isPrinting}
                            onClick={() =>
                              void handlePrintOne(
                                lot.inventoryLotLineId,
                                lot.lotNo,
                              )
                            }
                          >
                            {isPrinting ? (
                              <CircularProgress size={18} />
                            ) : (
                              "列印標籤"
                            )}
                          </Button>
                          {onWorkbenchScanPick ? (
                            <Button
                              variant="outlined"
                              color="secondary"
                              title={
                                !lotQrPayload
                                  ? "此列無法取得 QR payload（需 stockInLineId）"
                                  : disableScanPick
                                    ? "此出庫行已掃碼或已完成，無法顯示 QR"
                                  : undefined
                              }
                              disabled={
                                !canShowLotQr || !lotQrPayload || isPrinting
                              }
                              onClick={() =>
                                setQrVisibleLotLineId((prev) =>
                                  prev === lot.inventoryLotLineId
                                    ? null
                                    : lot.inventoryLotLineId,
                                )
                              }
                            >
                              顯示 QR
                            </Button>
                          ) : null}
                        </Stack>
                        {qrVisibleLotLineId === lot.inventoryLotLineId &&
                        lotQrPayload ? (
                          <Box
                            sx={{
                              mt: 1.5,
                              ml: "auto",
                              p: 1.5,
                              borderRadius: 1,
                              border: "1px dashed",
                              borderColor: "divider",
                              textAlign: "center",
                              minWidth: 220,
                            }}
                          >
                            <QRCodeSVG
                              value={JSON.stringify(lotQrPayload)}
                              size={160}
                              includeMargin
                            />
                          </Box>
                        ) : null}
                      </Box>
                    );
                  })}
                </Stack>
              )}
            </Box>
          )}

          {!analysis && !analysisLoading && (
            <Typography variant="body2" color="text.secondary">

              {onWorkbenchScanPick
                ? "沒有任何批號可列印標籤"
                : ""}
            </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 WorkbenchLotLabelPrintModal;
