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

export interface DeleteAccountInput {
  id: string;
}

/**
 * Function: deleteAccount
 *
 * Permanently removes a GL account in DRAFT status with no posted
 * transactions. ACTIVE/INACTIVE accounts and accounts with posted
 * transactions cannot be deleted.
 */
export async function run(db: Transaction, input: DeleteAccountInput, _ctx: CommandContext) {
  const { id } = input;

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

  if (!account) {
    return err(new AccountNotFoundError(id));
  }

  // 2. Look up parent CoA
  const coa = await db
    .selectFrom("ChartOfAccounts")
    .selectAll()
    .where("id", "=", account.chartOfAccountsId)
    .executeTakeFirst();

  // 3. CoA must be DRAFT or ACTIVE (not ARCHIVED)
  if (!coa || coa.status === "ARCHIVED") {
    return err(new ChartOfAccountsArchivedError(account.chartOfAccountsId));
  }

  // 4. Account must be DRAFT
  if (account.status !== "DRAFT") {
    return err(new InvalidStateTransitionError(id));
  }

  // 5. Must not have posted transactions
  if (account.hasPostedTransactions) {
    return err(new HasPostedTransactionsError(id));
  }

  // 6. Delete account
  await db.deleteFrom("Account").where("id", "=", id).execute();

  return ok({ success: true as const });
}
