"use client";

import { InventoryLotLineResult, InventoryResult } from "@/app/api/inventory";
import { updateInventoryLotLineStatus } from "@/app/api/inventory/actions";
import { arrayToDateString } from "@/app/utils/formatUtil";
import { msg, msgError } from "@/components/Swal/CustomAlerts";
import HighlightOffIcon from "@mui/icons-material/HighlightOff";
import {
  Box,
  FormControl,
  IconButton,
  InputLabel,
  MenuItem,
  Select,
  SelectChangeEvent,
  Typography,
} from "@mui/material";
import { useCallback, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { Column } from "../SearchResults";
import SearchResults, {
  defaultPagingController,
  defaultSetPagingController,
} from "../SearchResults/SearchResults";
import BadItemHandleModal from "./BadItemHandleModal";

const LOT_STATUSES = ["available", "unavailable"] as const;

interface Props {
  inventoryLotLines: InventoryLotLineResult[] | null;
  setPagingController: defaultSetPagingController;
  pagingController: typeof defaultPagingController;
  totalCount: number;
  inventory: InventoryResult | null;
  currentUserId?: number;
  onBadItemHandleSuccess?: (payload: {
    inventoryLotLineId: number;
    qty: number;
  }) => void | Promise<void>;
  onLotLinesChanged?: () => void | Promise<void>;
}

const StockIssueLotLineTable: React.FC<Props> = ({
  inventoryLotLines,
  pagingController,
  setPagingController,
  totalCount,
  inventory,
  currentUserId,
  onBadItemHandleSuccess,
  onLotLinesChanged,
}) => {
  const { t } = useTranslation(["stockIssue", "common"]);
  const [modalOpen, setModalOpen] = useState(false);
  const [selectedLotLine, setSelectedLotLine] =
    useState<InventoryLotLineResult | null>(null);
  const [statusUpdatingIds, setStatusUpdatingIds] = useState<Set<number>>(
    new Set(),
  );
  const statusInFlightRef = useRef<Set<number>>(new Set());

  const displayLotLines = useMemo(
    () => inventoryLotLines ?? [],
    [inventoryLotLines],
  );

  const isBadItemEnabled = useCallback((line: InventoryLotLineResult) => {
    const qty = line.availableQty ?? 0;
    return qty > 0;
  }, []);

  const handleBadItemClick = useCallback((lotLine: InventoryLotLineResult) => {
    if (!isBadItemEnabled(lotLine)) return;
    setSelectedLotLine(lotLine);
    setModalOpen(true);
  }, [isBadItemEnabled]);

  const handleStatusChange = useCallback(
    async (line: InventoryLotLineResult, event: SelectChangeEvent<string>) => {
      const nextStatus = event.target.value;
      if (!nextStatus || nextStatus === line.status) return;
      if (statusInFlightRef.current.has(line.id)) return;

      statusInFlightRef.current.add(line.id);
      setStatusUpdatingIds((prev) => new Set(prev).add(line.id));
      try {
        const res = await updateInventoryLotLineStatus({
          inventoryLotLineId: line.id,
          status: nextStatus,
        });
        if (res?.code && res.code !== "SUCCESS") {
          throw new Error(res.message ?? t("Failed to submit"));
        }
        msg(t("Saved successfully"));
        await onLotLinesChanged?.();
      } catch (e: unknown) {
        msgError(e instanceof Error ? e.message : t("Failed to submit"));
      } finally {
        statusInFlightRef.current.delete(line.id);
        setStatusUpdatingIds((prev) => {
          const next = new Set(prev);
          next.delete(line.id);
          return next;
        });
      }
    },
    [t, onLotLinesChanged],
  );

  const formatStatusLabel = useCallback(
    (status: string) => {
      const key = status?.toLowerCase();
      if (key === "available") return t("available");
      if (key === "unavailable") return t("unavailable");
      return status;
    },
    [t],
  );

  const columns = useMemo<Column<InventoryLotLineResult>[]>(
    () => [
      { name: "lotNo", label: t("Lot No") },
      {
        name: "availableQty",
        label: t("Available Qty"),
        align: "right",
        headerAlign: "right",
        type: "integer",
      },
      { name: "uom", label: t("Stock UoM") },
      {
        name: "expiryDate",
        label: t("Expiry Date"),
        renderCell: (params) => arrayToDateString(params.expiryDate),
      },
      {
        name: "warehouse",
        label: t("Warehouse"),
        renderCell: (params) => params.warehouse?.code ?? "",
      },
      {
        name: "status",
        label: t("Status"),
        renderCell: (row) => (
          <FormControl
            size="small"
            fullWidth
            disabled={statusUpdatingIds.has(row.id)}
          >
            <InputLabel id={`lot-status-${row.id}`}>{t("Status")}</InputLabel>
            <Select
              labelId={`lot-status-${row.id}`}
              label={t("Status")}
              value={
                LOT_STATUSES.includes(
                  row.status?.toLowerCase() as (typeof LOT_STATUSES)[number],
                )
                  ? row.status!.toLowerCase()
                  : "unavailable"
              }
              onChange={(e) => handleStatusChange(row, e)}
            >
              {LOT_STATUSES.map((s) => (
                <MenuItem key={s} value={s}>
                  {formatStatusLabel(s)}
                </MenuItem>
              ))}
            </Select>
          </FormControl>
        ),
      },
      {
        name: "id",
        label: t("Bad Item Handle"),
        align: "center",
        headerAlign: "center",
        renderCell: (row) => (
          <IconButton
            color="error"
            disabled={!isBadItemEnabled(row) || !currentUserId}
            onClick={() => handleBadItemClick(row)}
            title={t("Bad Item Handle")}
          >
            <HighlightOffIcon />
          </IconButton>
        ),
      },
    ],
    [
      t,
      handleStatusChange,
      formatStatusLabel,
      statusUpdatingIds,
      isBadItemEnabled,
      handleBadItemClick,
      currentUserId,
    ],
  );

  return (
    <>
      <Box sx={{ mb: 2 }}>
        <Typography variant="h6">
          {inventory
            ? `${t("Item selected")}: ${inventory.itemCode} | ${inventory.itemName} (${t(inventory.itemType, { ns: "common", defaultValue: inventory.itemType })})`
            : t("No items are selected yet.")}
        </Typography>
      </Box>
      <SearchResults<InventoryLotLineResult>
        items={displayLotLines}
        columns={columns}
        pagingController={pagingController}
        setPagingController={setPagingController}
        totalCount={totalCount}
      />
      <BadItemHandleModal
        open={modalOpen}
        onClose={() => setModalOpen(false)}
        lotLine={selectedLotLine}
        inventory={inventory}
        currentUserId={currentUserId}
        onSuccess={async (payload) => {
          await onBadItemHandleSuccess?.(payload);
        }}
      />
    </>
  );
};

export default StockIssueLotLineTable;
