import { ok, type ReadonlyDB } from "@tailor-platform/erp-kit/core";
import { Decimal } from "decimal.js";
import type { DB } from "../generated/kysely-tailordb";

export interface GetSiteStockSummaryInput {
  siteId: string;
  itemId?: string;
}

export async function run(db: ReadonlyDB<DB>, input: GetSiteStockSummaryInput) {
  const activeLocationIds = await db
    .selectFrom("StorageLocation")
    .select("id")
    .where("siteId", "=", input.siteId)
    .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: Decimal;
      totalReserved: Decimal;
      totalIncoming: Decimal;
      totalBlocked: Decimal;
      totalAvailable: Decimal;
    }
  >();

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

  const summary = Array.from(grouped.values()).map((entry) => ({
    itemId: entry.itemId,
    totalOnHand: entry.totalOnHand.toString(),
    totalReserved: entry.totalReserved.toString(),
    totalIncoming: entry.totalIncoming.toString(),
    totalBlocked: entry.totalBlocked.toString(),
    totalAvailable: entry.totalAvailable.toString(),
  }));

  return ok({ summary });
}
