"use server";

import { revalidateTag } from "next/cache";
import { BASE_API_URL } from "@/config/api";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import type {
  LaneBtn,
  PostPickOrderResponse,
  ReleasedDoPickOrderListItem,
  StoreLaneSummary,
} from "@/app/api/pickOrder/actions";
import dayjs from "dayjs";

/** Aligns with backend MessageResponse for workbench endpoints */
export type WorkbenchMessageResponse = {
  id?: number | null;
  code?: string | null;
  name?: string | null;
  type?: string | null;
  message?: string | null;
  errorPosition?: string | null;
  entity?: unknown;
};

export async function startWorkbenchBatchReleaseAsync(data: {
  ids: number[];
  userId: number;
}): Promise<WorkbenchMessageResponse> {
  const { ids, userId } = data;
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/batch-release/async?userId=${userId}`,
    {
      method: "POST",
      body: JSON.stringify(ids),
      headers: { "Content-Type": "application/json" },
    }
  );
}

/** V2: no SPL/stock out at batch release; created when assigning delivery_order_pick_order. */
export async function startWorkbenchBatchReleaseAsyncV2(data: {
  ids: number[];
  userId: number;
}): Promise<WorkbenchMessageResponse> {
  const { ids, userId } = data;
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/batch-release/async-v2?userId=${userId}`,
    {
      method: "POST",
      body: JSON.stringify(ids),
      headers: { "Content-Type": "application/json" },
    }
  );
}

export async function workbenchBatchReleaseSyncV2(data: {
  ids: number[];
  userId: number;
}): Promise<WorkbenchMessageResponse> {
  const { ids, userId } = data;
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/batch-release/sync-v1?userId=${userId}`,
    {
      method: "POST",
      body: JSON.stringify(ids),
      headers: { "Content-Type": "application/json" },
    }
  );
}

export async function getWorkbenchBatchReleaseProgress(
  jobId: string
): Promise<WorkbenchMessageResponse> {
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/batch-release/progress/${encodeURIComponent(jobId)}`,
    { method: "GET" }
  );
}

export type WorkbenchScanPickBody = {
  stockOutLineId: number;
  lotNo: string;
  /** From QR: ties to a single `inventory_lot` when lotNo is reused across stock-ins */
  stockInLineId?: number | null;
  /**
   * When set (e.g. label-print modal row), backend resolves this exact inventory lot line
   * instead of stockInLineId / newest-by-lotNo.
   */
  inventoryLotLineId?: number | null;
  /** Optional store scope (e.g. 2/F). When set, split re-suggestions must stay within the same store. */
  storeId?: string | null;
  /** Optional: exclude these warehouse codes from resuggest logic */
  excludeWarehouseCodes?: string[] | null;
  /** Optional decimal string or number serialized by JSON */
  qty?: number | string | null;
  userId: number;
};

function serializeWorkbenchQty(
  qty: number | string | null | undefined
): number | undefined {
  if (qty === null || qty === undefined || qty === "") return undefined;
  const n = typeof qty === "string" ? Number(qty) : qty;
  if (typeof n !== "number" || Number.isNaN(n) || !Number.isFinite(n)) return undefined;
  // 0 is a valid explicit workbench short submit (must be sent, not omitted)
  return n;
}

/**
 * DO workbench scan-pick. Omit `qty` for full remaining on this SOL chunk (backend may split if lot runs out).
 * Pass `qty` less than remaining for short submit (POL/SOL completed without `partially_completed` on POL).
 * Pass `qty` greater than remaining to overscan: backend posts up to lot availability, then rebuild/ensure SOL.
 */
export async function workbenchScanPick(
  body: WorkbenchScanPickBody
): Promise<WorkbenchMessageResponse> {
  const qty = serializeWorkbenchQty(body.qty);
  const sil = body.stockInLineId;
  const stockInLineId =
    typeof sil === "number" && Number.isFinite(sil) && sil > 0 ? sil : undefined;
  const storeId =
    typeof body.storeId === "string" && body.storeId.trim() !== ""
      ? body.storeId.trim()
      : undefined;
  const excludeWarehouseCodes =
    Array.isArray(body.excludeWarehouseCodes) && body.excludeWarehouseCodes.length > 0
      ? body.excludeWarehouseCodes
          .map((c) => (typeof c === "string" ? c.trim() : ""))
          .filter((c) => c !== "")
      : undefined;
  const ill = body.inventoryLotLineId;
  const inventoryLotLineId =
    typeof ill === "number" && Number.isFinite(ill) && ill > 0 ? ill : undefined;
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/scan-pick`,
    {
      method: "POST",
      body: JSON.stringify({
        stockOutLineId: body.stockOutLineId,
        lotNo: body.lotNo,
        ...(stockInLineId !== undefined ? { stockInLineId } : {}),
        ...(inventoryLotLineId !== undefined ? { inventoryLotLineId } : {}),
        ...(storeId !== undefined ? { storeId } : {}),
        ...(excludeWarehouseCodes !== undefined ? { excludeWarehouseCodes } : {}),
        ...(qty !== undefined ? { qty } : {}),
        userId: body.userId,
      }),
      headers: { "Content-Type": "application/json" },
    }
  );
}

export type WorkbenchBatchScanPickBody = {
  lines: WorkbenchScanPickBody[];
};

/**
 * DO workbench batch scan-pick.
 * Intended for batch-submit style flows where we close multiple SOLs (commonly qty=0 for noLot/expired/unavailable).
 */
export async function workbenchBatchScanPick(
  body: WorkbenchBatchScanPickBody,
): Promise<WorkbenchMessageResponse> {
  const lines = Array.isArray(body.lines) ? body.lines : [];
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/scan-pick/batch`,
    {
      method: "POST",
      body: JSON.stringify({
        lines: lines.map((l) => {
          const qty = serializeWorkbenchQty(l.qty);
          const sil = l.stockInLineId;
          const stockInLineId =
            typeof sil === "number" && Number.isFinite(sil) && sil > 0 ? sil : undefined;
          const storeId =
            typeof l.storeId === "string" && l.storeId.trim() !== "" ? l.storeId.trim() : undefined;
          const excludeWarehouseCodes =
            Array.isArray(l.excludeWarehouseCodes) && l.excludeWarehouseCodes.length > 0
              ? l.excludeWarehouseCodes
                  .map((c) => (typeof c === "string" ? c.trim() : ""))
                  .filter((c) => c !== "")
              : undefined;
          const ill = l.inventoryLotLineId;
          const inventoryLotLineId =
            typeof ill === "number" && Number.isFinite(ill) && ill > 0 ? ill : undefined;
          return {
            stockOutLineId: l.stockOutLineId,
            lotNo: l.lotNo ?? "",
            ...(stockInLineId !== undefined ? { stockInLineId } : {}),
            ...(inventoryLotLineId !== undefined ? { inventoryLotLineId } : {}),
            ...(storeId !== undefined ? { storeId } : {}),
            ...(excludeWarehouseCodes !== undefined ? { excludeWarehouseCodes } : {}),
            ...(qty !== undefined ? { qty } : {}),
            userId: l.userId,
          };
        }),
      }),
      headers: { "Content-Type": "application/json" },
    },
  );
}

/** Store lane grid backed by `delivery_order_pick_order` + `pick_order.deliveryOrderPickOrderId`. */
export async function fetchWorkbenchStoreLaneSummary(
  storeId: string,
  requiredDate?: string,
  releaseType?: string
): Promise<StoreLaneSummary> {
  const dateToUse = requiredDate || dayjs().format("YYYY-MM-DD");
  const rt = releaseType || "all";
  const url = `${BASE_API_URL}/doPickOrder/workbench/summary-by-store?storeId=${encodeURIComponent(storeId)}&requiredDate=${encodeURIComponent(dateToUse)}&releaseType=${encodeURIComponent(rt)}`;
  return serverFetchJson<StoreLaneSummary>(url, {
    method: "GET",
    cache: "no-store",
    next: { revalidate: 0 },
  });
}

/** All Etra tickets (`releaseType=isExtra`) for a calendar day, grouped by shop → lanes. */
export type WorkbenchEtraShopLaneGroup = {
  shopCode: string | null;
  shopName: string | null;
  lanes: LaneBtn[];
};

export async function fetchWorkbenchEtraLaneSummary(
  requiredDate?: string
): Promise<WorkbenchEtraShopLaneGroup[]> {
  const dateToUse = requiredDate || dayjs().format("YYYY-MM-DD");
  const url = `${BASE_API_URL}/doPickOrder/workbench/summary-is-etra?requiredDate=${encodeURIComponent(dateToUse)}`;
  const data = await serverFetchJson<WorkbenchEtraShopLaneGroup[]>(url, {
    method: "GET",
    cache: "no-store",
    next: { revalidate: 0 },
  });
  return Array.isArray(data) ? data : [];
}

/** Past-date `delivery_order_pick_order` tickets (same shape as `/doPickOrder/released`). */
export async function fetchWorkbenchReleasedDoPickOrdersForSelection(
  shopName?: string,
  storeId?: string,
  truck?: string,
  releaseType?: string
): Promise<ReleasedDoPickOrderListItem[]> {
  const params = new URLSearchParams();
  if (shopName?.trim()) params.append("shopName", shopName.trim());
  if (storeId?.trim()) params.append("storeId", storeId.trim());
  if (truck?.trim()) params.append("truck", truck.trim());
  if (releaseType?.trim()) params.append("releaseType", releaseType.trim());
  const query = params.toString();
  const url = `${BASE_API_URL}/doPickOrder/workbench/released${query ? `?${query}` : ""}`;
  const response = await serverFetchJson<ReleasedDoPickOrderListItem[]>(url, { method: "GET" });
  return response ?? [];
}

/** When `requiredDeliveryDate` is set (YYYY-MM-DD), filters `delivery_order_pick_order.requiredDeliveryDate`; otherwise calendar today. */
export async function fetchWorkbenchReleasedDoPickOrdersForSelectionToday(
  shopName?: string,
  storeId?: string,
  truck?: string,
  requiredDeliveryDate?: string,
  releaseType?: string
): Promise<ReleasedDoPickOrderListItem[]> {
  const params = new URLSearchParams();
  if (shopName?.trim()) params.append("shopName", shopName.trim());
  if (storeId?.trim()) params.append("storeId", storeId.trim());
  if (truck?.trim()) params.append("truck", truck.trim());
  if (requiredDeliveryDate?.trim()) params.append("requiredDate", requiredDeliveryDate.trim());
  if (releaseType?.trim()) params.append("releaseType", releaseType.trim());
  const query = params.toString();
  const url = `${BASE_API_URL}/doPickOrder/workbench/released-today${query ? `?${query}` : ""}`;
  const response = await serverFetchJson<ReleasedDoPickOrderListItem[]>(url, { method: "GET" });
  if (response == null) return [];
  return Array.isArray(response) ? response : [];
}

/** Same body as `/doPickOrder/assign-by-lane` but resolves `delivery_order_pick_order`. */
export async function assignWorkbenchByLane(data: {
  userId: number;
  storeId: string;
  truckLanceCode: string;
  truckDepartureTime?: string;
  loadingSequence?: number | null;
  requiredDate?: string;
  /** Backend normalizes to isExtra / isExtra filter on `delivery_order_pick_order.releaseType` */
  releaseType?: string;
}): Promise<PostPickOrderResponse> {
  const res = await serverFetchJson<PostPickOrderResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/assign-by-lane`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    }
  );
  revalidateTag("pickorder");
  return res;
}

/** Assign V1 (legacy): old FG-style, no atomic conflict guard. */
export async function assignWorkbenchByLaneV1(data: {
  userId: number;
  storeId: string;
  truckLanceCode: string;
  truckDepartureTime?: string;
  requiredDate?: string;
}): Promise<PostPickOrderResponse> {
  const res = await serverFetchJson<PostPickOrderResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/assign-by-lane-v1`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    }
  );
  revalidateTag("pickorder");
  return res;
}

export async function assignByDeliveryOrderPickOrderId(
  userId: number,
  deliveryOrderPickOrderId: number
): Promise<PostPickOrderResponse> {
  const res = await serverFetchJson<PostPickOrderResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/assign-by-delivery-order-pick-order-id`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ userId, deliveryOrderPickOrderId }),
    }
  );
  revalidateTag("pickorder");
  return res;
}

/** Assign V1 (legacy): old FG-style, no atomic conflict guard. */
export async function assignByDeliveryOrderPickOrderIdV1(
  userId: number,
  deliveryOrderPickOrderId: number
): Promise<PostPickOrderResponse> {
  const res = await serverFetchJson<PostPickOrderResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/assign-by-delivery-order-pick-order-id-v1`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ userId, deliveryOrderPickOrderId }),
    }
  );
  revalidateTag("pickorder");
  return res;
}

export async function fetchWorkbenchCompletedLotDetails(
  deliveryOrderPickOrderId: number,
): Promise<any> {
  return serverFetchJson<any>(
    `${BASE_API_URL}/doPickOrder/workbench/completed-lot-details/${deliveryOrderPickOrderId}`,
    { method: "GET" },
  );
}
export type WorkbenchScanPayload = {
  itemId: number;
  stockInLineId: number;
};
export async function fetchWorkbenchPrinters() {
  return serverFetchJson<any[]>(`${BASE_API_URL}/printers`, {
    method: "GET",
    cache: "no-store",
  });
}
export async function analyzeWorkbenchQrCode(payload: WorkbenchScanPayload) {
  return serverFetchJson<any>(`${BASE_API_URL}/inventoryLotLine/workbench/analyze-qr-code`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
    cache: "no-store",
  });
}

export async function fetchWorkbenchAvailableLotsByItem(itemId: number) {
  return serverFetchJson<any>(
    `${BASE_API_URL}/inventoryLotLine/workbench/available-lots-by-item/${itemId}`,
    {
      method: "GET",
      cache: "no-store",
    },
  );
}
/** Single DO; JSON body is one number (same as legacy `batch-release/async-single`). */
export async function startWorkbenchBatchReleaseAsyncSingleV2(data: {
  doId: number;
  userId: number;
}): Promise<WorkbenchMessageResponse> {
  const { doId, userId } = data;
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/doPickOrder/workbench/batch-release/async-single-v2?userId=${userId}`,
    {
      method: "POST",
      body: JSON.stringify(doId),
      headers: { "Content-Type": "application/json" },
    }
  );
}
export async function printWorkbenchLotLabel(params: {
  inventoryLotLineId: number;
  printerId: number;
  printQty: number;
}) {
  const searchParams = new URLSearchParams();
  searchParams.set("inventoryLotLineId", String(params.inventoryLotLineId));
  searchParams.set("printerId", String(params.printerId));
  searchParams.set("printQty", String(params.printQty));
  return serverFetchJson<WorkbenchMessageResponse>(
    `${BASE_API_URL}/inventoryLotLine/workbench/print-label?${searchParams.toString()}`,
    { method: "GET", cache: "no-store" },
  );
}