import type { DB } from "../generated/kysely-tailordb";
import { WarehouseNotFoundError } from "../lib/errors.generated";
import { ok, err, type ReadonlyDB } from "@tailor-platform/erp-kit/module";

export interface GetWarehouseStockSummaryInput {
  warehouseId: string;
  itemId?: string;
}

export async function run(db: ReadonlyDB<DB>, input: GetWarehouseStockSummaryInput) {
  const warehouse = await db
    .selectFrom("Warehouse")
    .selectAll()
    .where("id", "=", input.warehouseId)
    .executeTakeFirst();

  if (!warehouse) {
    return err(new WarehouseNotFoundError(input.warehouseId));
  }

  const activeLocationIds = await db
    .selectFrom("StorageLocation")
    .select("id")
    .where("warehouseId", "=", input.warehouseId)
    .where("status", "=", "ACTIVE")
    .execute();

  if (activeLocationIds.length === 0) {
    return ok({ summary: [] });
  }

  const locationIds = activeLocationIds.map((loc) => loc.id);

  let query = db
    .selectFrom("StockLevel")
    .select("itemId")
    .where("storageLocationId", "in", locationIds);

  if (input.itemId) {
    query = query.where("itemId", "=", input.itemId);
  }

  const stockLevels = await query.selectAll().execute();

  // Aggregate in-memory grouped by itemId
  const grouped = new Map<
    string,
    {
      itemId: string;
      totalOnHand: number;
      totalReserved: number;
      totalIncoming: number;
      totalBlocked: number;
      totalAvailable: number;
    }
  >();

  for (const sl of stockLevels) {
    const existing = grouped.get(sl.itemId);
    const available = sl.onHand - sl.reserved - sl.blocked;
    if (existing) {
      existing.totalOnHand += sl.onHand;
      existing.totalReserved += sl.reserved;
      existing.totalIncoming += sl.incoming;
      existing.totalBlocked += sl.blocked;
      existing.totalAvailable += available;
    } else {
      grouped.set(sl.itemId, {
        itemId: sl.itemId,
        totalOnHand: sl.onHand,
        totalReserved: sl.reserved,
        totalIncoming: sl.incoming,
        totalBlocked: sl.blocked,
        totalAvailable: available,
      });
    }
  }

  const summary = Array.from(grouped.values());

  return ok({ summary });
}
