import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/module";
import type { Transaction } from "../generated/kysely-tailordb";
import {
  FinancialStatementNotFoundError,
  InvalidStatusTransitionError,
} from "../lib/errors.generated";

export interface FinalizeFinancialStatementInput {
  id: string;
}

interface AuditEntry {
  type: string;
  from?: string;
  to?: string;
  actorId?: string;
}

/**
 * Function: finalizeFinancialStatement
 *
 * Transitions a financial statement from DRAFT to FINALIZED status.
 * Once finalized, the statement becomes immutable and cannot be
 * modified or regenerated.
 */
export async function run(
  db: Transaction,
  input: FinalizeFinancialStatementInput,
  ctx: CommandContext,
) {
  const { id } = input;
  const auditTrail: AuditEntry[] = [];

  // 1. Find FinancialStatement by id with forUpdate()
  const financialStatement = await db
    .selectFrom("FinancialStatement")
    .selectAll()
    .where("id", "=", id)
    .forUpdate()
    .executeTakeFirst();

  if (!financialStatement) {
    return err(new FinancialStatementNotFoundError(id));
  }

  // 2. Validate status is DRAFT
  if (financialStatement.status !== "DRAFT") {
    return err(new InvalidStatusTransitionError(id));
  }

  // 3. Update to FINALIZED, set finalizedAt to now
  const now = new Date();
  const updatedStatement = await db
    .updateTable("FinancialStatement")
    .set({
      status: "FINALIZED",
      finalizedAt: now,
      updatedAt: now,
    })
    .where("id", "=", id)
    .returningAll()
    .executeTakeFirst();

  // 4. Record audit event
  auditTrail.push({
    type: "STATUS_TRANSITION",
    from: "DRAFT",
    to: "FINALIZED",
    actorId: ctx.actorId,
  });

  return ok({ financialStatement: updatedStatement!, auditTrail });
}
