import { Injectable } from '@nestjs/common';
import {
  InvalidClientError,
  InvalidRequestError,
  type OAuthRevokeTokenInput,
  type OAuthRevokeTokenResponse,
} from '../../domain';
import { OAuthRevokeTokenService } from './services/o-auth-revoke-token.service';

/**
 * Composite handler for OAuth2 token revocation (RFC 7009) — one business flow, two transports.
 *
 * Both `OAuthRevokeTokenController` (REST `POST /api/o-auth/revoke`) and
 * `OAuthRevokeTokenResolver` (GraphQL `oAuthRevokeToken` mutation) parse their on-wire shape
 * into an `OAuthRevokeTokenInput` and call `handler.main(input)`. This handler owns the cheap
 * presence checks; the service authenticates the client against the store and performs the
 * revocation. The transports MUST NOT replicate any of this. See skill
 * `catalyst-handler-composer` → "Composite handlers" section.
 *
 * Revocation has a single path (no grant dispatch): the presented token is treated as a
 * refresh token, the only revocable credential that matters for this provider.
 */
@Injectable()
export class OAuthRevokeTokenHandler {
  constructor(private readonly revokeService: OAuthRevokeTokenService) {}

  async main(input: OAuthRevokeTokenInput): Promise<OAuthRevokeTokenResponse> {
    // RFC 7009 §2.1 / RFC 6749 §2.3.1 — the request must be client-authenticated. Empty
    // clientId or clientSecret means the transport could not present client credentials.
    if (!input.clientId || !input.clientSecret) {
      throw new InvalidClientError();
    }

    // RFC 7009 §2.1 — the `token` parameter is required.
    if (!input.token) {
      throw new InvalidRequestError();
    }

    return this.revokeService.main(input);
  }
}
