"use client";

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,
  StockIssueLists,
  StockIssueResult,
  submitBadItem,
  submitExpiryItem,
  submitMissItem,
} from "@/app/api/stockIssue/actions";
import { Box, Button, Tab, Tabs } from "@mui/material";
import { useSession } from "next-auth/react";

interface Props {
  dataList: StockIssueLists;
}

type SearchQuery = {
  lotNo: string;
};
type SearchParamNames = keyof SearchQuery;

const SearchPage: React.FC<Props> = ({ dataList }) => {
  const { t } = useTranslation("inventory");
  const [tab, setTab] = useState<"miss" | "bad" | "expiry">("miss");
  const [search, setSearch] = useState<SearchQuery>({ lotNo: "" });
  const { data: session } = useSession() as { data: SessionWithTokens | null };
  const currentUserId = session?.id ? parseInt(session.id) : undefined;
  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 searchCriteria: Criterion<SearchParamNames>[] = useMemo(
    () => [
      {
        label: t("Lot No."),
        paramName: "lotNo",
        type: "text",
      },
    ],
    [t],
  );

  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;
      }

      setSubmittingIds((prev) => new Set(prev).add(id));
      try {
        if (tab === "miss") {
          await submitMissItem(id, currentUserId);
          setMissItems((prev) => prev.filter((i) => i.id !== id));
        } else if (tab === "bad") {
          await submitBadItem(id, currentUserId);
          setBadItems((prev) => prev.filter((i) => i.id !== id));
        } else {
          await submitExpiryItem(id, currentUserId);
          setExpiryItems((prev) => prev.filter((i) => i.id !== id));
        }
        // Remove from selectedIds if it was selected
        setSelectedIds((prev) => prev.filter((selectedId) => selectedId !== id));
      } catch (error) {
        console.error("Failed to submit item:", error);
        alert(`Failed to submit: ${error instanceof Error ? error.message : "Unknown error"}`);
      } finally {
        setSubmittingIds((prev) => {
          const newSet = new Set(prev);
          newSet.delete(id);
          return newSet;
        });
      }
    },
    [tab, currentUserId, t],
  );

  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);
    try {
      if (tab === "miss") {
        await batchSubmitMissItem(allIds, currentUserId);
        setMissItems((prev) => prev.filter((i) => !allIds.includes(i.id)));
      } else if (tab === "bad") {
        await batchSubmitBadItem(allIds, currentUserId);
        setBadItems((prev) => prev.filter((i) => !allIds.includes(i.id)));
      } else {
        await batchSubmitExpiryItem(allIds, currentUserId);
        setExpiryItems((prev) => prev.filter((i) => !allIds.includes(i.id)));
      }

      setSelectedIds([]);
    } catch (error) {
      console.error("Failed to submit selected items:", error);
      alert(`Failed to submit: ${error instanceof Error ? error.message : "Unknown error"}`);
    } finally {
      setBatchSubmitting(false);
    }
  }, [tab, currentUserId, missItems, badItems, expiryItems, filterBySearch]);

  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: "missQty", label: t("Miss 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("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: "badItemQty", label: t("Defective 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 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") },
      { 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((query: Record<SearchParamNames, string>) => {
    setSearch(query);
  }, []);

  const handleTabChange = useCallback(
    (_: React.SyntheticEvent, value: string) => {
      setTab(value as "miss" | "bad" | "expiry");
      setSelectedIds([]);
    },
    [],
  );

  const renderCurrentTab = () => {
    if (tab === "miss") {
      const items = filterBySearch(missItems);
      return (
        <SearchResults<StockIssueResult>
          items={items}
          columns={missColumns}
          pagingController={{ pageNum: 1, pageSize: 10 }}
          checkboxIds={selectedIds}
          setCheckboxIds={setSelectedIds}
        />
      );
    }

    if (tab === "bad") {
      const items = filterBySearch(badItems);
      return (
        <SearchResults<StockIssueResult>
          items={items}
          columns={badColumns}
          pagingController={{ pageNum: 1, pageSize: 10 }}
          checkboxIds={selectedIds}
          setCheckboxIds={setSelectedIds}
        />
      );
    }

    const items = filterBySearch(expiryItems);
    return (
      <SearchResults<ExpiryItemResult>
        items={items}
        columns={expiryColumns}
        pagingController={{ pageNum: 1, pageSize: 10 }}
        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}
      />

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

      {renderCurrentTab()}
    </Box>
  );
};

export default SearchPage;