import type { Transaction } from "../generated/kysely-tailordb";
import {
  ChannelOrderNotFoundError,
  ExceptionContextRequiredError,
  InvalidChannelOrderStatusError,
} from "../lib/errors.generated";
import { encodeJson } from "../lib/domain";
import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/module";

export interface MarkChannelOrderExceptionInput {
  channelOrderId: string;
  errorSummary?: string;
  retryContext?: Record<string, unknown> | null;
}

export async function run(
  db: Transaction,
  input: MarkChannelOrderExceptionInput,
  ctx: CommandContext,
) {
  void ctx;
  const channelOrder = await db
    .selectFrom("ChannelOrder")
    .selectAll()
    .where("id", "=", input.channelOrderId)
    .forUpdate()
    .executeTakeFirst();
  if (!channelOrder) {
    return err(new ChannelOrderNotFoundError(input.channelOrderId));
  }
  if (channelOrder.status !== "PENDING_CONVERSION") {
    return err(new InvalidChannelOrderStatusError(input.channelOrderId));
  }
  if (!input.errorSummary && !input.retryContext) {
    return err(new ExceptionContextRequiredError(input.channelOrderId));
  }
  const updated = await db
    .updateTable("ChannelOrder")
    .set({
      status: "EXCEPTION",
      errorSummary: input.errorSummary ?? channelOrder.errorSummary,
      retryContext: input.retryContext ? encodeJson(input.retryContext) : channelOrder.retryContext,
      updatedAt: new Date(),
    })
    .where("id", "=", input.channelOrderId)
    .returningAll()
    .executeTakeFirst();
  return ok({ channelOrder: updated! });
}
