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 MCS = Selectable<"ManufacturingCostSummary">;
type PO = Selectable<"ProductionOrder">;
type OrderByField = "status" | "createdAt" | "updatedAt";

export type ListManufacturingCostSummariesByStatusInput = Pick<PO, "companyId"> &
  Partial<Pick<PO, "siteId">> &
  Partial<Pick<MCS, "productionOrderId">> & {
    status: MCS["status"] | MCS["status"][];
  } & PaginationInput<OrderByField>;

export async function run(db: ReadonlyDB<DB>, input: ListManufacturingCostSummariesByStatusInput) {
  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 orderDirection = input.orderDirection ?? "asc";

  let query = db
    .selectFrom("ManufacturingCostSummary")
    .innerJoin(
      "ProductionOrder",
      "ProductionOrder.id",
      "ManufacturingCostSummary.productionOrderId",
    )
    .select([
      "ManufacturingCostSummary.id",
      "ManufacturingCostSummary.productionOrderId",
      "ManufacturingCostSummary.plannedMaterialCost",
      "ManufacturingCostSummary.plannedLaborCost",
      "ManufacturingCostSummary.plannedMachineCost",
      "ManufacturingCostSummary.plannedOverheadCost",
      "ManufacturingCostSummary.actualMaterialCost",
      "ManufacturingCostSummary.actualLaborCost",
      "ManufacturingCostSummary.actualMachineCost",
      "ManufacturingCostSummary.actualOverheadCost",
      "ManufacturingCostSummary.currencyCode",
      "ManufacturingCostSummary.reviewedDate",
      "ManufacturingCostSummary.reviewerNotes",
      "ManufacturingCostSummary.status",
      "ManufacturingCostSummary.createdAt",
      "ManufacturingCostSummary.updatedAt",
    ])
    .where("ProductionOrder.companyId", "=", input.companyId)
    .where("ManufacturingCostSummary.status", "in", statuses);

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

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

  const orderBy = input.orderBy ?? "id";
  const items = await query
    .orderBy(`ManufacturingCostSummary.${orderBy}`, orderDirection)
    .limit(limit + 1)
    .offset(offset)
    .execute();

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