import {
  ok,
  err,
  type ReadonlyDB,
  type PaginationInput,
  buildPaginatedResult,
  DEFAULT_PAGE_SIZE,
} from "@tailor-platform/erp-kit/core";
import type { DB, Selectable } from "../generated/kysely-tailordb";
import { StatusFilterRequiredError, CompanyScopeRequiredError } from "../lib/errors.generated";

type PO = Selectable<"ProductionOrder">;

export type ListProductionOrdersByStatusInput = Pick<PO, "companyId"> &
  Partial<Pick<PO, "siteId" | "orderedItemId">> & {
    status: PO["status"] | PO["status"][];
    plannedStartDateFrom?: PO["plannedStartDate"];
    plannedStartDateTo?: PO["plannedStartDate"];
  } & PaginationInput<"plannedStartDate">;

export async function run(db: ReadonlyDB<DB>, input: ListProductionOrdersByStatusInput) {
  if (!input.companyId) {
    return err(new CompanyScopeRequiredError("companyId"));
  }

  const statuses = Array.isArray(input.status) ? input.status : input.status ? [input.status] : [];
  if (statuses.length === 0) {
    return err(new StatusFilterRequiredError("status"));
  }

  const limit = input.limit ?? DEFAULT_PAGE_SIZE;
  const offset = input.offset ?? 0;
  const orderBy = input.orderBy ?? "plannedStartDate";
  const orderDirection = input.orderDirection ?? "asc";

  let query = db
    .selectFrom("ProductionOrder")
    .selectAll()
    .where("companyId", "=", input.companyId)
    .where("status", "in", statuses);

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

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

  if (input.plannedStartDateFrom) {
    query = query.where("plannedStartDate", ">=", input.plannedStartDateFrom);
  }

  if (input.plannedStartDateTo) {
    query = query.where("plannedStartDate", "<=", input.plannedStartDateTo);
  }

  const rows = await query
    .orderBy(orderBy, orderDirection)
    .limit(limit + 1)
    .offset(offset)
    .execute();

  // Fetch linked cost-summary statuses for the returned production orders
  const orderIds = rows.map((r) => r.id);
  const costSummaries =
    orderIds.length > 0
      ? await db
          .selectFrom("ManufacturingCostSummary")
          .select(["productionOrderId", "status"])
          .where("productionOrderId", "in", orderIds)
          .execute()
      : [];

  const costStatusMap = new Map(costSummaries.map((cs) => [cs.productionOrderId, cs.status]));

  const items = rows.map((row) => ({
    ...row,
    costSummaryStatus: costStatusMap.get(row.id) ?? null,
  }));

  return ok(buildPaginatedResult(items, limit));
}
