"use client";
import dayjs from "dayjs";
import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import SearchBox, { Criterion } from "../SearchBox";
import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import SearchResults, { Column } from "../SearchResults/index";
import { SessionWithTokens } from "@/config/authConfig";
import {
  batchSubmitBadItem,
  batchSubmitExpiryItem,
  batchSubmitMissItem,
  ExpiryItemResult,
  fetchExpiryItemList,
  StockIssueLists,
  StockIssueResult,
  submitBadItem,
  submitExpiryItem,
  submitMissItem,
} from "@/app/api/stockIssue/actions";
import { Box, Button, Tab, Tabs } from "@mui/material";
import { useSession } from "next-auth/react";
import SubmitIssueForm from "./SubmitIssueForm";

interface Props {
  dataList: StockIssueLists;
}

type SearchQuery = {
  lotNo: string;
  itemCode: string;
  itemName: string;
  expiryDate: string;
};
type SearchParamNames = keyof SearchQuery;

const SearchPage: React.FC<Props> = ({ dataList }) => {
  const BATCH_CHUNK_SIZE = 20;
  const { t } = useTranslation("inventory");
  const [tab, setTab] = useState<"miss" | "bad" | "expiry">("miss");
  const [search, setSearch] = useState<SearchQuery>({
    lotNo: "",
    itemCode: "",
    itemName: "",
    expiryDate: "",
  });
  const { data: session } = useSession() as { data: SessionWithTokens | null };
  const currentUserId = session?.id ? parseInt(session.id) : undefined;
  const [formOpen, setFormOpen] = useState(false);
  const [selectedLotId, setSelectedLotId] = useState<number | null>(null);
  const [selectedItemId, setSelectedItemId] = useState<number>(0);
  const [selectedIssueType, setSelectedIssueType] = useState<"miss" | "bad">("miss");

  const [missItems, setMissItems] = useState<StockIssueResult[]>(
    dataList.missItems,
  );
  const [badItems, setBadItems] = useState<StockIssueResult[]>(
    dataList.badItems,
  );
  const [expiryItems, setExpiryItems] = useState<ExpiryItemResult[]>(
    dataList.expiryItems,
  );
  const [selectedIds, setSelectedIds] = useState<(string | number)[]>([]);
  const [submittingIds, setSubmittingIds] = useState<Set<number>>(new Set());
  const [batchSubmitting, setBatchSubmitting] = useState(false);
  const [batchProgress, setBatchProgress] = useState<{ done: number; total: number } | null>(null);
  const [paging, setPaging] = useState({ pageNum: 1, pageSize: 10 });
  const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
    () => {
      if (tab === "expiry") {
        return [
          {
            label: t("Item Code"),
            paramName: "itemCode",
            type: "text",
          },
          {
            label: t("Item"),
            paramName: "itemName",
            type: "text",
          },
          {
            label: t("Expiry Date"),
            paramName: "expiryDate",
            type: "date",
          },
        ];
      }

      return [
        {
          label: t("Lot No."),
          paramName: "lotNo",
          type: "text",
        },
      ];
    },
    [t, tab],
  );

  const filterBySearch = useCallback(
    <T extends { lotNo: string | null }>(items: T[]): T[] => {
      if (!search.lotNo) return items;
      const keyword = search.lotNo.toLowerCase();
      return items.filter(
        (i) => i.lotNo && i.lotNo.toLowerCase().includes(keyword),
      );
    },
    [search.lotNo],
  );

  const handleSubmitSingle = useCallback(
    async (id: number) => {
      if (!currentUserId) {
        alert(t("User ID is required"));
        return;
      }

      // Find the item to get lotId
      let lotId: number | null = null;
      let itemId = 0;
      
      if (tab === "miss") {
        const item = missItems.find((i) => i.id === id);
        if (item) {
          lotId = item.lotId;
          itemId = item.itemId;
        }
      } else if (tab === "bad") {
        const item = badItems.find((i) => i.id === id);
        if (item) {
          lotId = item.lotId;
          itemId = item.itemId;
        }
      } else if (tab === "expiry") {
        const item = expiryItems.find((i) => i.id === id);
        if (!item) {
          alert(t("Item not found"));
          return;
        }
      
        try {
          // 如果想要 loading 效果，可以这里把 id 加进 submittingIds
          await submitExpiryItem(item.id, currentUserId);
          // 成功后，从列表移除这一行，或直接 reload
          // setExpiryItems(prev => prev.filter(i => i.id !== id));
          window.location.reload();
        } catch (e) {
          console.error("submitExpiryItem failed:", e);
          const errMsg = e instanceof Error ? e.message : t("Unknown error");
          alert(`${t("Failed to submit expiry item")}: ${errMsg}`);
        }
        return; // 记得 return，避免再走到下面的 lotId/itemId 分支
      }

      if (lotId && itemId) {
        setSelectedLotId(lotId);
        setSelectedItemId(itemId);
        setSelectedIssueType(tab === "miss" ? "miss" : "bad");
        setFormOpen(true);
      } else {
        alert(t("Item not found"));
      }
    },
    [tab, currentUserId, t, missItems, badItems, expiryItems]
  );

  const handleFormSuccess = useCallback(() => {
    // Refresh the lists
    if (tab === "miss") {
      // Reload miss items - you may need to add a refresh function
      window.location.reload(); // Or use a proper refresh mechanism
    } else if (tab === "bad") {
      // Reload bad items
      window.location.reload(); // Or use a proper refresh mechanism
    }
  }, [tab]);

  const handleSubmitSelected = useCallback(async () => {
    if (!currentUserId) return;
    
    // Get all IDs from the current tab's filtered items
    let allIds: number[] = [];
    if (tab === "miss") {
      const items = filterBySearch(missItems);
      allIds = items.map((item) => item.id);
    } else if (tab === "bad") {
      const items = filterBySearch(badItems);
      allIds = items.map((item) => item.id);
    } else {
      const items = filterBySearch(expiryItems);
      allIds = items.map((item) => item.id);
    }

    if (allIds.length === 0) return;

    setBatchSubmitting(true);
    setBatchProgress({ done: 0, total: allIds.length });
    try {
      for (let i = 0; i < allIds.length; i += BATCH_CHUNK_SIZE) {
        const chunkIds = allIds.slice(i, i + BATCH_CHUNK_SIZE);

        if (tab === "miss") {
          await batchSubmitMissItem(chunkIds, currentUserId);
          setMissItems((prev) => prev.filter((item) => !chunkIds.includes(item.id)));
        } else if (tab === "bad") {
          await batchSubmitBadItem(chunkIds, currentUserId);
          setBadItems((prev) => prev.filter((item) => !chunkIds.includes(item.id)));
        } else {
          await batchSubmitExpiryItem(chunkIds, currentUserId);
          setExpiryItems((prev) => prev.filter((item) => !chunkIds.includes(item.id)));
        }

        setBatchProgress({
          done: Math.min(i + chunkIds.length, allIds.length),
          total: allIds.length,
        });
      }

      setSelectedIds([]);
    } catch (error) {
      console.error("Failed to submit selected items:", error);
      const partialDone = batchProgress?.done ?? 0;
      alert(
        `${t("Failed to submit")}: ${error instanceof Error ? error.message : "Unknown error"} (${partialDone}/${allIds.length})`
      );
    } finally {
      setBatchSubmitting(false);
      setBatchProgress(null);
    }
  }, [tab, currentUserId, missItems, badItems, expiryItems, filterBySearch, batchProgress, t]);

  const missColumns = useMemo<Column<StockIssueResult>[]>(
    () => [
      { name: "itemCode", label: t("Item Code") },
      { name: "itemDescription", label: t("Item") },
      { name: "lotNo", label: t("Lot No.") },
      { name: "storeLocation", label: t("Location") },
      {
        name: "bookQty",
        label: t("Book Qty"),
        renderCell: (item) => (
          <>{item.bookQty?.toFixed(2) ?? "0"} {item.uomDesc ?? ""}</>
        ),
      },
      { name: "issueQty", label: t("Miss Qty") },
      { name: "uomDesc", label: t("UoM"), renderCell: (item) => (
        <>{item.uomDesc ?? ""}</>
      ) },
      {
        name: "id",
        label: t("Action"),
        renderCell: (item) => (
          <Button
            size="small"
            variant="contained"
            color="primary"
            onClick={() => handleSubmitSingle(item.id)}
            disabled={submittingIds.has(item.id) || !currentUserId}
          >
            {submittingIds.has(item.id) ? t("Processing...") : t("Looked")}
          </Button>
        ),
      },
    ],
    [t, handleSubmitSingle, submittingIds, currentUserId],
  );

  const badColumns = useMemo<Column<StockIssueResult>[]>(
    () => [
      { name: "itemCode", label: t("Item Code") },
      { name: "itemDescription", label: t("Item") },
      { name: "lotNo", label: t("Lot No.") },
      { name: "storeLocation", label: t("Location") },
      { name: "issueQty", label: t("Defective Qty") },
      { name: "uomDesc", label: t("UoM"), renderCell: (item) => (
        <>{item.uomDesc ?? ""}</>
      ) },
      {
        name: "id",
        label: t("Action"),
        renderCell: (item) => (
          <Button
            size="small"
            variant="contained"
            color="primary"
            onClick={() => handleSubmitSingle(item.id)}
            disabled={submittingIds.has(item.id) || !currentUserId}
          >
            {submittingIds.has(item.id) ? t("Disposing...") : t("Disposed")}
          </Button>
        ),
      },
    ],
    [t, handleSubmitSingle, submittingIds, currentUserId],
  );

  const expiryColumns = useMemo<Column<ExpiryItemResult>[]>(
    () => [
      { name: "itemCode", label: t("Item Code") },
      { name: "itemDescription", label: t("Item") },
      { name: "lotNo", label: t("Lot No.") },
      { name: "storeLocation", label: t("Location") },
      {
        name: "expiryDate",
        label: t("Expiry Date"),
        renderCell: (item) => {
          const raw = String(item.expiryDate ?? "").trim();
          if (!raw) return "—";
          let d;
          if (raw.includes(",")) {
            const parts = raw.split(",").map((s) => parseInt(s.trim(), 10));
          const [y, m, d_] = parts;
          if (parts.length >= 3 && y != null && m != null && d_ != null && !Number.isNaN(y) && !Number.isNaN(m) && !Number.isNaN(d_)) {
            d = dayjs(new Date(y, m - 1, d_));
          } else {
            d = dayjs("");
          }
          } else {
            let normalized = raw;
            if (raw.length === 7) {
              normalized = raw.slice(0, 4) + "0" + raw.slice(4, 5) + raw.slice(5, 7);
            } else if (raw.length === 6) {
              normalized = raw.slice(0, 4) + "0" + raw.slice(4, 5) + "0" + raw.slice(5, 6);
            }
            d = dayjs(normalized, "YYYYMMDD", true);
          }
          return d.isValid() ? d.format(OUTPUT_DATE_FORMAT) : raw;
        },
      },
      { name: "remainingQty", label: t("Remaining Qty") },
      {
        name: "id",
        label: t("Action"),
        renderCell: (item) => (
          <Button
            size="small"
            variant="contained"
            color="primary"
            onClick={() => handleSubmitSingle(item.id)}
            disabled={submittingIds.has(item.id) || !currentUserId}
          >
            {submittingIds.has(item.id) ? t("Disposing...") : t("Disposed")}
          </Button>
        ),
      },
    ],
    [t, handleSubmitSingle, submittingIds, currentUserId],
  );

  const handleSearch = useCallback(async (query: Record<SearchParamNames, string>) => {
    setSearch(query);
    setPaging((prev) => ({ ...prev, pageNum: 1 }));

    if (tab !== "expiry") {
      return;
    }

    try {
      const result = await fetchExpiryItemList({
        itemCode: query.itemCode?.trim() || undefined,
        itemName: query.itemName?.trim() || undefined,
        expiryDate: query.expiryDate || undefined,
      });
      setExpiryItems(result);
      setSelectedIds([]);
    } catch (error) {
      console.error("Failed to search expiry items:", error);
      alert(t("Failed to load expiry items"));
    }
  }, [tab, t]);

  const handleTabChange = useCallback(
    (_: React.SyntheticEvent, value: string) => {
      setTab(value as "miss" | "bad" | "expiry");
      setSelectedIds([]);
      setPaging((prev) => ({ ...prev, pageNum: 1 }));  // 新增：切 Tab 时回到第 1 页
    },
    [],
  );

  const renderCurrentTab = () => {
    if (tab === "miss") {
      const items = filterBySearch(missItems);
      return (
        <SearchResults<StockIssueResult>
          items={items}
          columns={missColumns}
          pagingController={paging}
          checkboxIds={selectedIds}
          setPagingController={setPaging}
          setCheckboxIds={setSelectedIds}
        />
      );
    }

    if (tab === "bad") {
      const items = filterBySearch(badItems);
      return (
        <SearchResults<StockIssueResult>
          items={items}
          columns={badColumns}
          pagingController={paging}
          setPagingController={setPaging}
          checkboxIds={selectedIds}
          setCheckboxIds={setSelectedIds}
        />
      );
    }

    const items = filterBySearch(expiryItems);
    return (
      <SearchResults<ExpiryItemResult>
        items={items}
        columns={expiryColumns}
        pagingController={paging}
        setPagingController={setPaging}
        checkboxIds={selectedIds}
        setCheckboxIds={setSelectedIds}
      />
    );
  };

  return (
    <Box>
      <Tabs value={tab} onChange={handleTabChange} sx={{ mb: 2 }}>
        <Tab value="miss" label={t("Miss Item")} />
        <Tab value="bad" label={t("Bad Item")} />
        <Tab value="expiry" label={t("Expiry Item")} />
      </Tabs>

      <SearchBox<SearchParamNames>
        criteria={searchCriteria}
        onSearch={handleSearch}
      />

{tab === "expiry" && (
  <Box sx={{ display: "flex", justifyContent: "flex-end", mb: 1 }}>
    <Button
      variant="contained"
      color="primary"
      onClick={handleSubmitSelected}
      disabled={batchSubmitting || !currentUserId}
    >
      {batchSubmitting
        ? `${t("Disposing...")} ${batchProgress ? `(${batchProgress.done}/${batchProgress.total})` : ""}`
        : t("Batch Disposed All")}
    </Button>
  </Box>
)}

      {renderCurrentTab()}
      <SubmitIssueForm
        open={formOpen}
        onClose={() => setFormOpen(false)}
        lotId={selectedLotId}
        itemId={selectedItemId}
        issueType={selectedIssueType}
        currentUserId={currentUserId || 0}
        onSuccess={handleFormSuccess}
      />
    </Box>
  );
};

export default SearchPage;