import { ok, type ReadonlyDB, DEFAULT_PAGE_SIZE } from "@tailor-platform/erp-kit/core";
import type { StockAdjustmentAdjustmentType, StockAdjustmentStatus } from "../generated/enums";
import type { DB } from "../generated/kysely-tailordb";

export interface ListStockAdjustmentsInput {
  adjustmentType?: StockAdjustmentAdjustmentType;
  status?: StockAdjustmentStatus;
  dateFrom?: Date;
  dateTo?: Date;
  limit?: number;
  offset?: number;
}

export async function run(db: ReadonlyDB<DB>, input: ListStockAdjustmentsInput) {
  const limit = input.limit ?? DEFAULT_PAGE_SIZE;
  const offset = input.offset ?? 0;

  let query = db.selectFrom("StockAdjustment").selectAll();

  if (input.adjustmentType) {
    query = query.where("adjustmentType", "=", input.adjustmentType);
  }
  if (input.status) {
    query = query.where("status", "=", input.status);
  }
  if (input.dateFrom) {
    query = query.where("createdAt", ">=", input.dateFrom);
  }
  if (input.dateTo) {
    query = query.where("createdAt", "<=", input.dateTo);
  }

  const adjustments = await query
    .orderBy("createdAt", "desc")
    .limit(limit + 1)
    .offset(offset)
    .execute();

  const hasNextPage = adjustments.length > limit;
  const pagedAdjustments = hasNextPage ? adjustments.slice(0, limit) : adjustments;

  // Fetch lines for all returned adjustments in a single query
  const adjustmentIds = pagedAdjustments.map((a) => a.id);
  let allLines: { stockAdjustmentId: string; [key: string]: unknown }[] = [];

  if (adjustmentIds.length > 0) {
    allLines = (await db
      .selectFrom("StockAdjustmentLine")
      .selectAll()
      .where("stockAdjustmentId", "in", adjustmentIds)
      .execute()) as { stockAdjustmentId: string; [key: string]: unknown }[];
  }

  // Group lines by stockAdjustmentId
  const linesByAdjustmentId = new Map<string, typeof allLines>();
  for (const line of allLines) {
    const existing = linesByAdjustmentId.get(line.stockAdjustmentId) ?? [];
    existing.push(line);
    linesByAdjustmentId.set(line.stockAdjustmentId, existing);
  }

  const items = pagedAdjustments.map((adj) => ({
    stockAdjustment: adj,
    stockAdjustmentLines: linesByAdjustmentId.get(adj.id) ?? [],
  }));

  return ok({ items, hasNextPage });
}
