/**
 * @aurora-catalyst-generated
 * @source cliter/o-auth/authorization-code.aurora.yaml
 */
import { OAuthAuthorizationCode } from '@api/graphql';
import { OAuthAuthorizationCodeModel } from '@app/o-auth/authorization-code';
import { AuditingRunner, ICriteria, SequelizeCatalystRepository } from '@aurorajs.dev/core-back';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';

@Injectable()
export class OAuthSequelizeAuthorizationCodeRepository extends SequelizeCatalystRepository<
  OAuthAuthorizationCodeModel,
  OAuthAuthorizationCode
> {
  constructor(
    @InjectModel(OAuthAuthorizationCodeModel)
    public readonly repository: typeof OAuthAuthorizationCodeModel,
    public readonly criteria: ICriteria,
    public readonly auditingRunner: AuditingRunner,
  ) {
    super();
  }

  /**
   * Atomically marks an authorization code as used using a conditional UPDATE.
   *
   * Implements the single-use invariant from decision D4:
   *   UPDATE o_auth_authorization_code SET is_used = true WHERE id = ? AND is_used = false
   *
   * Returns `true` when exactly 1 row was updated (successful first-use), or `false` when
   * 0 rows were updated (code was already used or does not exist). The caller MUST treat
   * `false` as `invalid_grant` and abort token issuance.
   *
   * Manually maintained — survives regen via Cliter's .origin three-way merge.
   */
  async consumeCode(id: string): Promise<boolean> {
    const [affectedCount] = await this.repository.update(
      { isUsed: true },
      { where: { id, isUsed: false } },
    );
    return affectedCount === 1;
  }
}
