import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core";
import { transferOrderLifecycle } from "../db/transferOrder.lifecycle.generated";
import type { Transaction } from "../generated/kysely-tailordb";
import { isTransferOrderInTransitClear } from "../internal/transferOrderProgress";
import {
  InvalidStateTransitionError,
  TransferOrderInTransitError,
  TransferOrderNotFoundError,
} from "../lib/errors.generated";

export interface CloseTransferOrderInput {
  id: string;
}

export async function run(db: Transaction, input: CloseTransferOrderInput, _ctx: CommandContext) {
  const existing = await db
    .selectFrom("TransferOrder")
    .selectAll()
    .where("id", "=", input.id)
    .forUpdate()
    .executeTakeFirst();
  if (!existing) {
    return err(new TransferOrderNotFoundError(input.id));
  }

  const nextStatus = transferOrderLifecycle.tryTransition(existing.status, "close");
  if (!nextStatus) {
    return err(new InvalidStateTransitionError(input.id));
  }

  const lines = await db
    .selectFrom("TransferOrderLine")
    .selectAll()
    .where("transferOrderId", "=", input.id)
    .execute();
  if (!isTransferOrderInTransitClear(lines)) {
    return err(new TransferOrderInTransitError(input.id));
  }

  const stockReservations = await db
    .updateTable("StockReservation")
    .set({ status: "CLOSED" })
    .where("sourceType", "=", "TRANSFER_ORDER")
    .where("sourceId", "=", input.id)
    .where("status", "=", "OPEN")
    .returningAll()
    .execute();

  const supplyPlans = await db
    .updateTable("InventorySupplyPlan")
    .set({ status: "CLOSED" })
    .where("sourceType", "=", "TRANSFER_ORDER")
    .where("sourceId", "=", input.id)
    .where("status", "=", "OPEN")
    .returningAll()
    .execute();

  const transferOrder = await db
    .updateTable("TransferOrder")
    .set({ status: nextStatus, closedAt: new Date() })
    .where("id", "=", input.id)
    .returningAll()
    .executeTakeFirstOrThrow();

  return ok({ transferOrder, stockReservations, supplyPlans });
}
