import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core";
import { manufacturingCostSummaryLifecycle } from "../db/manufacturingCostSummary.lifecycle.generated";
import type { Transaction } from "../generated/kysely-tailordb";
import {
  CostSummaryNotFoundError,
  CostSummaryNotSettlableError,
  AcknowledgmentMismatchError,
  AcknowledgmentRejectedOrSupersededError,
  AcknowledgmentSourceInvalidError,
} from "../lib/errors.generated";

export interface RecordManufacturingCostSettlementAcknowledgmentInput {
  costSummaryId: string;
  productionOrderId: string;
  currencyCode: string;
  settlementReference: string;
  settlementDate: string;
  acknowledgedDate?: string | null;
  acknowledgmentStatus?: string | null;
  acknowledgmentSource?: string | null;
}

/**
 * Function: recordManufacturingCostSettlementAcknowledgment
 *
 * Persists the downstream accounting acknowledgment that a reviewed
 * manufacturing cost handoff has been consumed by settlement processing.
 * It is the only path that moves a reviewed summary to SETTLED.
 */
export async function run(
  db: Transaction,
  input: RecordManufacturingCostSettlementAcknowledgmentInput,
  _ctx: CommandContext,
) {
  const {
    costSummaryId,
    productionOrderId,
    currencyCode,
    settlementReference,
    settlementDate,
    acknowledgedDate,
    acknowledgmentStatus,
    acknowledgmentSource,
  } = input;

  // 1. Validate acknowledgment source
  if (!acknowledgmentSource) {
    return err(new AcknowledgmentSourceInvalidError(costSummaryId));
  }

  // 2. Resolve cost summary
  const costSummary = await db
    .selectFrom("ManufacturingCostSummary")
    .selectAll()
    .where("id", "=", costSummaryId)
    .forUpdate()
    .executeTakeFirst();

  if (!costSummary) {
    return err(new CostSummaryNotFoundError(costSummaryId));
  }

  // 3. Summary must be VARIANCE_REVIEWED
  const nextStatus = manufacturingCostSummaryLifecycle.tryTransition(costSummary.status, "settle");
  if (!nextStatus) {
    return err(new CostSummaryNotSettlableError(costSummaryId));
  }

  // 4. Validate payload matches the reviewed summary's identity and currency
  if (
    costSummary.productionOrderId !== productionOrderId ||
    costSummary.currencyCode !== currencyCode
  ) {
    return err(new AcknowledgmentMismatchError(costSummaryId));
  }

  // 5. Check that downstream accounting accepted (not rejected/reversed/superseded)
  if (
    acknowledgmentStatus === "REJECTED" ||
    acknowledgmentStatus === "REVERSED" ||
    acknowledgmentStatus === "SUPERSEDED"
  ) {
    return err(new AcknowledgmentRejectedOrSupersededError(costSummaryId));
  }

  // 6. Create settlement record
  await db
    .insertInto("ManufacturingCostSettlementRecord")
    .values({
      costSummaryId: costSummary.id,
      settlementDate: new Date(settlementDate),
      settlementReference,
      acknowledgedDate: acknowledgedDate ? new Date(acknowledgedDate) : new Date(),
    })
    .returningAll()
    .executeTakeFirst();

  // 7. Update summary to SETTLED
  const updatedSummary = await db
    .updateTable("ManufacturingCostSummary")
    .set({
      status: nextStatus,
    })
    .where("id", "=", costSummary.id)
    .returningAll()
    .executeTakeFirstOrThrow();

  return ok({ manufacturingCostSummary: updatedSummary });
}
