"use client";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
  Box,
  Button,
  Card,
  CardContent,
  CardActions,
  Stack,
  Typography,
  Chip,
  CircularProgress,
  TablePagination,
  Grid,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  Checkbox,
  ListItemText,
  SelectChangeEvent,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
} from "@mui/material";
import { useTranslation } from "react-i18next";
import { fetchItemForPutAway } from "@/app/api/stockIn/actions";
import QcStockInModal from "../Qc/QcStockInModal";
import { useSession } from "next-auth/react";
import { SessionWithTokens } from "@/config/authConfig";
import dayjs from "dayjs";
import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import SearchBox, { Criterion } from "@/components/SearchBox/SearchBox";
import { AUTH } from "@/authorities";


import {
  AllJoborderProductProcessInfoResponse,
  updateJo,
  fetchProductProcessesByJobOrderId,
  completeProductProcessLine,
  assignJobOrderPickOrder,
  fetchJoborderProductProcessesPage
} from "@/app/api/jo/actions";
import { StockInLineInput } from "@/app/api/stockIn";
import { PrinterCombo } from "@/app/api/settings/printer";
import JobPickExecutionsecondscan from "../Jodetail/JobPickExecutionsecondscan";
export type ProductionProcessListPersistedState = {
  date: string;
  itemCode: string | null;
  jobOrderCode: string | null;
  filter: "all" | "drink" | "Powder_Mixture" | "other";
  page: number;
  selectedItemCodes: string[];
};

interface ProductProcessListProps {
  onSelectProcess: (jobOrderId: number|undefined, productProcessId: number|undefined) => void;
  onSelectMatchingStock: (jobOrderId: number|undefined, productProcessId: number|undefined,pickOrderId: number|undefined) => void;
  printerCombo: PrinterCombo[];
  qcReady: boolean;
  includePutaway?: boolean | null;
  /** all | completed | notCompleted */
  putawayStatus?: string | null;
  disableDateFilter?: boolean;
  listPersistedState: ProductionProcessListPersistedState;
  onListPersistedStateChange: React.Dispatch<
    React.SetStateAction<ProductionProcessListPersistedState>
  >;
}
export type SearchParam = "date" | "itemCode" | "jobOrderCode" | "processType";

const PAGE_SIZE = 50;

/** 預設依 JobOrder.planStart 搜索：今天往前 3 天～往後 3 天（含當日） */
function defaultPlanStartRange() {
  return {
    from: dayjs().subtract(0, "day").format("YYYY-MM-DD"),
    to: dayjs().add(0, "day").format("YYYY-MM-DD"),
  };
}

export function createDefaultProductionProcessListPersistedState(): ProductionProcessListPersistedState {
  return {
    date: dayjs().format("YYYY-MM-DD"),
    itemCode: null,
    jobOrderCode: null,
    filter: "all",
    page: 0,
    selectedItemCodes: [],
  };
}

const ProductProcessList: React.FC<ProductProcessListProps> = ({
  onSelectProcess,
  printerCombo,
  onSelectMatchingStock,
  qcReady,
  includePutaway,
  putawayStatus,
  disableDateFilter = false,
  listPersistedState,
  onListPersistedStateChange,
}) => {
  const { t } = useTranslation( ["common", "productionProcess","purchaseOrder","dashboard"]);
  const { data: session } = useSession() as { data: SessionWithTokens | null };
  const sessionToken = session as SessionWithTokens | null;
  const [loading, setLoading] = useState(false);
  const [processes, setProcesses] = useState<AllJoborderProductProcessInfoResponse[]>([]);
  const [openModal, setOpenModal] = useState<boolean>(false);
  const [modalInfo, setModalInfo] = useState<StockInLineInput>();
  const currentUserId = session?.id ? parseInt(session.id) : undefined; 
  const abilities = session?.abilities ?? session?.user?.abilities ?? [];
  // 依照 DB `authority.authority = 'ADMIN'` 的逻辑：僅 abilities 明確包含 ADMIN 才能操作
  const canManageUpdateJo = abilities.some((a) => a.trim() === AUTH.ADMIN);
  type ProcessFilter = "all" | "drink" | "Powder_Mixture" | "other";
  const [suggestedLocationCode, setSuggestedLocationCode] = useState<string | null>(null);

  const appliedSearch = useMemo(
    () => ({
      date: listPersistedState.date,
      itemCode: listPersistedState.itemCode,
      jobOrderCode: listPersistedState.jobOrderCode,
    }),
    [
      listPersistedState.date,
      listPersistedState.itemCode,
      listPersistedState.jobOrderCode,
    ],
  );
  const filter = listPersistedState.filter;
  const page = listPersistedState.page;
  const selectedItemCodes = listPersistedState.selectedItemCodes;

  const [totalJobOrders, setTotalJobOrders] = useState(0);

  // Generic confirm dialog for actions (update job order / etc.)
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [confirmMessage, setConfirmMessage] = useState("");
  const [confirmLoading, setConfirmLoading] = useState(false);
  const [pendingConfirmAction, setPendingConfirmAction] = useState<null | (() => Promise<void>)>(null);

  // QC 的业务判定：同一个 jobOrder 下，所有 productProcess 的所有 lines 都必须是 Completed/Pass
  // 才允许打开 QcStockInModal（避免仅某个 productProcess 完成就提前出现 view stockin）。
  const jobOrderQcReadyById = useMemo(() => {
    const lineDone = (status: unknown) => {
      const s = String(status ?? "").trim().toLowerCase();
      return s === "completed" || s === "pass";
    };

    const byJobOrder = new Map<number, AllJoborderProductProcessInfoResponse[]>();
    for (const p of processes) {
      if (p.jobOrderId == null) continue;
      const arr = byJobOrder.get(p.jobOrderId) ?? [];
      arr.push(p);
      byJobOrder.set(p.jobOrderId, arr);
    }

    const result = new Map<number, boolean>();
    const isDone = (status: unknown) => {
      const s = String(status ?? "").trim().toLowerCase();
      return s === "completed" || s === "pass";
    };
    
    byJobOrder.forEach((jobOrderProcesses, jobOrderId) => {
      const hasStockInLine = jobOrderProcesses.some((p) => p.stockInLineId != null);
    
      const packingProcesses = jobOrderProcesses.filter(
        (p) => String((p as any).code ?? "").trim() === "包裝"
      );
      const nonPackingProcesses = jobOrderProcesses.filter(
        (p) => String((p as any).code ?? "").trim() !== "包裝"
      );
    
      const allNonPackingDone =
      nonPackingProcesses.length === 0 ||
      nonPackingProcesses.every((p) => {
        const lines = p.lines ?? [];
        return lines.length > 0 && lines.every((l) => isDone(l.status));
      });
    
      const hasOnePackingDone =
        packingProcesses.length > 0 &&
        packingProcesses.some((p) => {
          const lines = p.lines ?? [];
          return lines.some((l) => isDone(l.status));
        });
    
      const packingOk = packingProcesses.length === 0 ? true : hasOnePackingDone;
    
      result.set(jobOrderId, hasStockInLine && allNonPackingDone && packingOk);
    });

    return result;
  }, [processes]);
  const handleAssignPickOrder = useCallback(async (pickOrderId: number, jobOrderId?: number, productProcessId?: number) => {
    if (!currentUserId) {
      alert(t("Unable to get user ID"));
      return;
    }

    try {
      console.log("🔄 Assigning pick order:", pickOrderId, "to user:", currentUserId);
      
      // 调用分配 API 并读取响应
      const assignResult = await assignJobOrderPickOrder(pickOrderId, currentUserId);
      
      console.log("📦 Assign result:", assignResult);
      
      // 检查分配是否成功
      if (assignResult.message === "Successfully assigned") {
        console.log("✅ Successfully assigned pick order");
        console.log("✅ Pick order ID:", assignResult.id);
        console.log("✅ Pick order code:", assignResult.code);
        
        // 分配成功后，导航到 second scan 页面
        if (onSelectMatchingStock && jobOrderId) {
          onSelectMatchingStock(jobOrderId, productProcessId,pickOrderId);
        } else {
          alert(t("Assignment successful"));
        }
      } else {
        // 分配失败
        console.error("Assignment failed:", assignResult.message);
        alert(t(`Assignment failed: ${assignResult.message || "Unknown error"}`));
      }
    } catch (error: any) {
      console.error(" Error assigning pick order:", error);
      alert(t(`Unknown error: ${error?.message || "Unknown error"}。Please try again later.`));
    }
  }, [currentUserId, t, onSelectMatchingStock]);

  const handleViewStockIn = useCallback((process: AllJoborderProductProcessInfoResponse) => {
    if (!process.stockInLineId) {
      alert(t("Invalid Stock In Line Id"));
      return;
    }
  
    setModalInfo({
      id: process.stockInLineId,
     //itemId: process.itemId, // 如果 process 中有 itemId，添加这一行
      //expiryDate: dayjs().add(1, "month").format(OUTPUT_DATE_FORMAT),
    });
    setOpenModal(true);
  }, [t]);

  const handleApplySearch = useCallback(
    (inputs: Record<SearchParam | `${SearchParam}To`, string>) => {
      const selectedProcessType = (inputs.processType || "all") as ProcessFilter;
      onListPersistedStateChange((prev) => ({
        ...prev,
        filter: selectedProcessType,
        date: disableDateFilter ? "" : (inputs.date || "").trim(),
        itemCode: inputs.itemCode?.trim() ? inputs.itemCode.trim() : null,
        jobOrderCode: inputs.jobOrderCode?.trim() ? inputs.jobOrderCode.trim() : null,
        selectedItemCodes: [],
        page: 0,
      }));
    },
    [disableDateFilter, onListPersistedStateChange],
  );

  const handleResetSearch = useCallback(() => {
    onListPersistedStateChange((prev) => ({
      ...prev,
      filter: "all",
      date: disableDateFilter ? "" : defaultPlanStartRange().from,
      itemCode: null,
      jobOrderCode: null,
      selectedItemCodes: [],
      page: 0,
    }));
  }, [disableDateFilter, onListPersistedStateChange]);

  const fetchProcesses = useCallback(async () => {
    setLoading(true);
    try {
      const typeParam = filter === "all" ? undefined : filter;

      const data = await fetchJoborderProductProcessesPage({
        date: disableDateFilter ? undefined : appliedSearch.date,
        itemCode: appliedSearch.itemCode,
        jobOrderCode: appliedSearch.jobOrderCode,
        qcReady,
        includePutaway: includePutaway ?? (qcReady ? true : null),
        putawayStatus,
        type: typeParam,
        page,
        size: PAGE_SIZE,
      });

      setProcesses(data?.content || []);
      setTotalJobOrders(data?.totalJobOrders || 0);
    } catch (e) {
      console.error(e);
      setProcesses([]);
      setTotalJobOrders(0);
    } finally {
      setLoading(false);
    }
  }, [appliedSearch, disableDateFilter, filter, qcReady, includePutaway, putawayStatus, page]);

  useEffect(() => {
    fetchProcesses();
  }, [fetchProcesses]);
  const handleUpdateJo = useCallback(async (process: AllJoborderProductProcessInfoResponse) => {
    if (!canManageUpdateJo) return;
    if (!process.jobOrderId) {
      alert(t("Invalid Job Order Id"));
      return;
    }
    try {
      setLoading(true); // 可选：已有 loading state 可复用
      // 1) 拉取该 JO 的所有 process，取出全部 lineId
      const processes = await fetchProductProcessesByJobOrderId(process.jobOrderId);
      const lineIds = (processes ?? [])
        .flatMap(p => (p as any).productProcessLines ?? [])
        .map(l => l.id)
        .filter(Boolean);
  
      // 2) 逐个调用 completeProductProcessLine
      for (const lineId of lineIds) {
        try {
          await completeProductProcessLine(lineId);
        } catch (e) {
          console.error("completeProductProcessLine failed for lineId:", lineId, e);
        }
      }
  
      // 3) 更新 JO 状态
     // await updateJo({ id: process.jobOrderId, status: "completed" });
  
      // 4) 刷新列表
      await fetchProcesses();
    } catch (e) {
      console.error(e);
      alert(t("An error has occurred. Please try again later."));
    } finally {
      setLoading(false);
    }
  }, [t, fetchProcesses, canManageUpdateJo]);

  const openConfirm = useCallback((message: string, action: () => Promise<void>) => {
    setConfirmMessage(message);
    setPendingConfirmAction(() => action);
    setConfirmOpen(true);
  }, []);

  const closeConfirm = useCallback(() => {
    setConfirmOpen(false);
    setPendingConfirmAction(null);
    setConfirmMessage("");
    setConfirmLoading(false);
  }, []);

  const onConfirm = useCallback(async () => {
    if (!pendingConfirmAction) return;
    setConfirmLoading(true);
    try {
      await pendingConfirmAction();
    } finally {
      closeConfirm();
    }
  }, [pendingConfirmAction, closeConfirm]);
  const closeNewModal = useCallback(() => {
    // const response = updateJo({ id: 1, status: "storing" });
    setOpenModal(false); // Close the modal first
   // fetchProcesses();
    // setTimeout(() => {
    //   }, 300); // Add a delay to avoid immediate re-trigger of useEffect
}, [fetchProcesses]);

  const searchedItemOptions = useMemo(
    () =>
      Array.from(
        new Map(
          processes
            .filter((p) => !!p.itemCode)
            .map((p) => [p.itemCode, { itemCode: p.itemCode, itemName: p.itemName }]),
        ).values(),
      ),
    [processes],
  );

  const paged = useMemo(() => {
    if (selectedItemCodes.length === 0) return processes;
    return processes.filter((p) => selectedItemCodes.includes(p.itemCode));
  }, [processes, selectedItemCodes]);

  /** Reset 用 ±3 天；preFilled 用目前已套用的條件（與列表查詢一致） */
  const searchCriteria: Criterion<SearchParam>[] = useMemo(() => {
    const base: Criterion<SearchParam>[] = [
      ...(disableDateFilter
        ? []
        : [{
        type: "date",
        label: t("Search date"),
        paramName: "date",
        defaultValue: appliedSearch.date,
        preFilledValue: appliedSearch.date,
      } as Criterion<SearchParam>]),
      {
        type: "text",
        label: t("Item Code"),
        paramName: "itemCode",
        preFilledValue: appliedSearch.itemCode ?? "",
      },
      {
        type: "text",
        label: t("Job Order Code"),
        paramName: "jobOrderCode",
        preFilledValue: appliedSearch.jobOrderCode ?? "",
      },
      {
        type: "select",
        label: t("Process Type"),
        paramName: "processType",
        options: ["all", "drink", "Powder_Mixture", "other"],
        preFilledValue: filter,
      },
    ];
    return base;
  }, [appliedSearch, disableDateFilter, filter, t]);

  /** SearchBox 內部 state 只在掛載時讀 preFilled；套用搜索後需 remount 才會與 appliedSearch 一致 */
  const searchBoxKey = useMemo(
    () =>
      [
        disableDateFilter ? "" : appliedSearch.date,
        appliedSearch.itemCode ?? "",
        appliedSearch.jobOrderCode ?? "",
        filter,
      ].join("|"),
    [appliedSearch, disableDateFilter, filter],
  );

  const handleSelectedItemCodesChange = useCallback(
    (e: SelectChangeEvent<string[]>) => {
      const nextValue = e.target.value;
      const codes = typeof nextValue === "string" ? nextValue.split(",") : nextValue;
      onListPersistedStateChange((prev) => ({ ...prev, selectedItemCodes: codes }));
    },
    [onListPersistedStateChange],
  );

  return (
    <Box>
      {loading ? (
        <Box sx={{ display: "flex", justifyContent: "center", p: 3 }}>
          <CircularProgress />
        </Box>
      ) : (
        <Box>
          <SearchBox<SearchParam>
            key={searchBoxKey}
            criteria={searchCriteria}
            onSearch={handleApplySearch}
            onReset={handleResetSearch}
            extraActions={
              <FormControl size="small" sx={{ minWidth: 260 }}>
                <InputLabel>{t("Searched Item")}</InputLabel>
                <Select
                  multiple
                  value={selectedItemCodes}
                  label={t("Item Code")}
                  renderValue={(selected) =>
                    (selected as string[]).length === 0 ? t("All") : (selected as string[]).join(", ")
                  }
                  onChange={handleSelectedItemCodesChange}
                >
                  {searchedItemOptions.map((item) => (
                    <MenuItem key={item.itemCode} value={item.itemCode}>
                      <Checkbox checked={selectedItemCodes.includes(item.itemCode)} />
                      <ListItemText primary={[item.itemCode, item.itemName].filter(Boolean).join(" - ")} />
                    </MenuItem>
                  ))}
                </Select>
              </FormControl>
            }
          />
          <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
            {!disableDateFilter && (
              <>
                {t("Search date")}:{" "}
                {appliedSearch.date && dayjs(appliedSearch.date).isValid()
                  ? dayjs(appliedSearch.date).format(OUTPUT_DATE_FORMAT)
                  : "-"}
                {" | "}
              </>
            )}
            {t("Total job orders")}: {totalJobOrders}
            {selectedItemCodes.length > 0 ? ` | ${t("Filtered")}: ${paged.length}` : ""}
          </Typography>

          <Grid container spacing={2}>
            {paged.map((process) => {
              const status = String(process.status || "");
              const statusLower = status.toLowerCase();
              const displayStatus = statusLower === "in_progress" ? "processing" : status;
              const statusColor =
                statusLower === "completed"
                  ? "success"
                  : statusLower === "in_progress" || statusLower === "processing"
                  ? "primary"
                  : "default";

                  const finishedCount =
                  (process.lines || []).filter(
                    (l) => String(l.status ?? "").trim().toLowerCase() === "completed" || String(l.status ?? "").trim().toLowerCase() === "pass"
                  ).length;

              const totalCount = process.productProcessLineCount ?? process.lines?.length ?? 0;
              const linesWithStatus = (process.lines || []).filter(
                (l) => String(l.status ?? "").trim() !== ""
              );

              const dateDisplay = process.date
                ? dayjs(process.date as any).format(OUTPUT_DATE_FORMAT)
                : "-";
              const jobOrderCode =
                (process as any).jobOrderCode ??
                (process.jobOrderId ? `JO-${process.jobOrderId}` : "N/A");
                const inProgressLines = (process.lines || [])
                .filter(l => String(l.status ?? "").trim() !== "")
                .filter(l => String(l.status).toLowerCase() === "in_progress");

              const canQc =
                process.jobOrderId != null &&
                process.stockInLineId != null &&
                jobOrderQcReadyById.get(process.jobOrderId) === true;

              return (
                <Grid key={process.id} item xs={12} sm={6} md={4}>
                  <Card
                    sx={{
                      minHeight: 180,
                      maxHeight: 320,            
                      display: "flex",
                      flexDirection: "column",
                      border: "1px solid",
                      borderColor: "blue",
                    }}
                  >
                    <CardContent
                      sx={{
                        pb: 1,
                        flexGrow: 1,            // let content take remaining height
                        overflow: "auto",       // allow scroll when content exceeds
                      }}
                    >
                      <Stack direction="row" justifyContent="space-between" alignItems="center">
                        <Box sx={{ minWidth: 0 }}>
                          <Typography variant="subtitle1">
                          {t("Job Order")}: {jobOrderCode}
                          </Typography>
                    
                    
                        </Box>
                        <Chip size="small" label={t(displayStatus)} color={statusColor as any} />
                      </Stack>
                      <Typography variant="body2" color="text.secondary">
                        {t("Lot No")}: {process.lotNo ?? "-"}
                      </Typography>
                      <Typography variant="subtitle1" color="blue">
                       {/* <strong>{t("Item Name")}:</strong> */}
                         {process.itemCode} {process.itemName}
                         {process.bomDescription ? ` (${t(process.bomDescription as string)})` : ""}
                      </Typography>
                      <Typography variant="body2" color="text.secondary">
                        {t("Production Priority")}: {process.productionPriority}
                      </Typography>
                      <Typography variant="body2" color="text.secondary">
                        {t("Required Qty")}: {process.requiredQty} ({process.uom})
                      </Typography>
                      <Typography variant="body2" color="text.secondary">
                        {t("Production date")}: {process.date ? dayjs(process.date as any).format(OUTPUT_DATE_FORMAT) : "-"}
                      </Typography>
                      <Typography variant="body2" color="text.secondary">
                        {t("Assume Time Need")}: {process.timeNeedToComplete} {t("minutes")}
                      </Typography>
                      {statusLower !== "pending" && linesWithStatus.length > 0 && (
                        <Box sx={{ mt: 1 }}>
                          <Typography variant="body2" fontWeight={600}>
                            {t("Finished lines")}: {finishedCount} / {totalCount}
                          </Typography>

                          {inProgressLines.length > 0 && (
                            <Box sx={{ mt: 1 }}>
                              {inProgressLines.map(line => (
                                <Typography key={line.id} variant="caption" color="text.secondary" display="block">
                                  {t("Operator")}: {line.operatorName || "-"} <br />
                                  {t("Equipment")}: {line.equipmentName || "-"}
                                </Typography>
                              ))}
                            </Box>
                          )}
                        </Box>
                      )}
                      {statusLower == "pending" && (
                        <Box sx={{ mt: 1 }}>
                           <Typography variant="body2" fontWeight={600} color= "white">
                            {t("Pending")}
                          </Typography>
                          <Box sx={{ mt: 1 }}>
                          <Typography variant="caption" color="text.secondary" display="block">
                                  {""}
                           </Typography>
                            </Box>
                        </Box>
                      )}
        
                    </CardContent>

                    <CardActions sx={{ pt: 0.5 }}>
                      <Button variant="contained" size="small" onClick={() => onSelectProcess(process.jobOrderId, process.id)}>
                        {t("View Details")}
                      </Button>
                      <Button 
                      variant="contained" 
                      size="small" 
                      disabled={process.assignedTo != null || process.matchStatus == "completed"|| process.pickOrderStatus != "completed"} 
                      onClick={() => handleAssignPickOrder(process.pickOrderId, process.jobOrderId, process.id)}
                    >
                      {t("Matching Stock")}
                    </Button>
                  
                      {statusLower !== "completed" && (
                      <Button
                        variant="contained"
                        size="small"
                        disabled={!canManageUpdateJo}
                        onClick={() =>
                          canManageUpdateJo
                            ? openConfirm(
                                t("Confirm to update this Job Order?"),
                                async () => {
                                  await handleUpdateJo(process);
                                }
                              )
                            : undefined
                        }
                      >
                        {t("Update Job Order")}
                      </Button>
                      )}

                      {canQc && (
                        <Button variant="contained" size="small" onClick={() => handleViewStockIn(process)}>
                          {t("view stockin")}
                        </Button>
                      )}
                      <Box sx={{ flex: 1 }} />
                     
                    </CardActions>
                  </Card>
                </Grid>
              );
            })}
          </Grid>
          <QcStockInModal
            session={sessionToken}
            open={openModal}
            onClose={closeNewModal}
            inputDetail={modalInfo}
            printerCombo={printerCombo}
            warehouse={[]}
            printSource="productionProcess"
            uiMode="default"
          />
          <Dialog open={confirmOpen} onClose={closeConfirm} maxWidth="xs" fullWidth>
            <DialogTitle>{t("Confirm")}</DialogTitle>
            <DialogContent>
              <Typography variant="body2">{confirmMessage}</Typography>
            </DialogContent>
            <DialogActions>
              <Button onClick={closeConfirm} disabled={confirmLoading}>
                {t("Cancel")}
              </Button>
              <Button
                variant="contained"
                onClick={onConfirm}
                disabled={confirmLoading || !pendingConfirmAction}
              >
                {confirmLoading ? t("Processing...") : t("Confirm")}
              </Button>
            </DialogActions>
          </Dialog>
          {totalJobOrders > 0 && (
            <TablePagination
              component="div"
              count={totalJobOrders}
              page={page}
              rowsPerPage={PAGE_SIZE}
              onPageChange={(e, p) =>
                onListPersistedStateChange((prev) => ({ ...prev, page: p }))
              }
              rowsPerPageOptions={[PAGE_SIZE]}
            />
          )}
        </Box>
      )}
    </Box>
    
  );
};

export default ProductProcessList;