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

export interface GetProductionOrderInput {
  id: string;
}

/**
 * Function: getProductionOrder
 *
 * Returns one production order with release snapshots, material and work-order
 * details, and execution rollups for end-to-end planner review.
 */
export async function run(db: ReadonlyDB<DB>, input: GetProductionOrderInput) {
  const productionOrder = await db
    .selectFrom("ProductionOrder")
    .selectAll()
    .where("id", "=", input.id)
    .executeTakeFirst();

  if (!productionOrder) {
    return err(new ProductionOrderNotFoundError(input.id));
  }

  const bomSnapshot = await db
    .selectFrom("ProductionOrderBomSnapshot")
    .selectAll()
    .where("productionOrderId", "=", productionOrder.id)
    .executeTakeFirst();

  const routingSnapshot = await db
    .selectFrom("ProductionOrderRoutingSnapshot")
    .selectAll()
    .where("productionOrderId", "=", productionOrder.id)
    .executeTakeFirst();

  const costBaseline = await db
    .selectFrom("ProductionOrderCostBaseline")
    .selectAll()
    .where("productionOrderId", "=", productionOrder.id)
    .executeTakeFirst();

  const materialRequirements = await db
    .selectFrom("ProductionOrderMaterialRequirement")
    .selectAll()
    .where("productionOrderId", "=", productionOrder.id)
    .execute();

  const workOrders = await db
    .selectFrom("WorkOrder")
    .selectAll()
    .where("productionOrderId", "=", productionOrder.id)
    .orderBy("routingOperationSequenceNumber", "asc")
    .execute();

  const costSummary = await db
    .selectFrom("ManufacturingCostSummary")
    .selectAll()
    .where("productionOrderId", "=", productionOrder.id)
    .executeTakeFirst();

  const quantityRollup = {
    plannedQuantity: productionOrder.plannedQuantity,
    completedQuantity: workOrders.reduce((sum, workOrder) => sum + workOrder.completedQuantity, 0),
    scrapQuantity: workOrders.reduce((sum, workOrder) => sum + workOrder.scrapQuantity, 0),
    actualSetupTime: workOrders.reduce((sum, workOrder) => sum + workOrder.actualSetupTime, 0),
    actualRunTime: workOrders.reduce((sum, workOrder) => sum + workOrder.actualRunTime, 0),
    openWorkOrderCount: workOrders.filter(
      (workOrder) => workOrder.status !== "COMPLETE" && workOrder.status !== "CANCELLED",
    ).length,
  };

  return ok({
    productionOrder,
    bomSnapshot: bomSnapshot ?? null,
    routingSnapshot: routingSnapshot ?? null,
    costBaseline: costBaseline ?? null,
    materialRequirements,
    workOrders,
    quantityRollup,
    costSummary: costSummary ?? null,
  });
}
