import { request } from '../request.js';
import type {
  Credential,
  CredentialWithSecret,
  GenerateCredentialRequest,
  ListCredentialsParams,
  PaginatedCredentials,
} from '../types.js';

/**
 * Client for the Credential Management service.
 * Covers generate, list, rotate, and revoke operations for agent credentials.
 */
export class CredentialClient {
  constructor(
    private readonly baseUrl: string,
    private readonly getToken: () => Promise<string>,
  ) {}

  /**
   * Generate a new credential for an agent.
   * The `clientSecret` in the response is shown ONCE — store it securely immediately.
   */
  async generateCredential(
    agentId: string,
    params: GenerateCredentialRequest = {},
  ): Promise<CredentialWithSecret> {
    const token = await this.getToken();
    return request<CredentialWithSecret>(this.baseUrl, {
      method: 'POST',
      path: `/api/v1/agents/${agentId}/credentials`,
      token,
      body: Object.keys(params).length > 0 ? params : undefined,
    });
  }

  /**
   * List all credentials for an agent with optional pagination.
   * Secrets are never returned in list responses.
   */
  async listCredentials(
    agentId: string,
    params: ListCredentialsParams = {},
  ): Promise<PaginatedCredentials> {
    const token = await this.getToken();
    return request<PaginatedCredentials>(this.baseUrl, {
      method: 'GET',
      path: `/api/v1/agents/${agentId}/credentials`,
      token,
      query: {
        page: params.page,
        limit: params.limit,
      },
    });
  }

  /**
   * Rotate a credential. The same credentialId is retained but a new secret is issued.
   * The old secret is immediately invalidated upon rotation.
   * The new `clientSecret` is shown ONCE — store it securely immediately.
   */
  async rotateCredential(agentId: string, credentialId: string): Promise<CredentialWithSecret> {
    const token = await this.getToken();
    return request<CredentialWithSecret>(this.baseUrl, {
      method: 'POST',
      path: `/api/v1/agents/${agentId}/credentials/${credentialId}/rotate`,
      token,
    });
  }

  /**
   * Revoke a credential. Any tokens previously issued with this credential
   * remain valid until they expire — use token revocation to invalidate them immediately.
   */
  async revokeCredential(agentId: string, credentialId: string): Promise<Credential> {
    const token = await this.getToken();
    return request<Credential>(this.baseUrl, {
      method: 'DELETE',
      path: `/api/v1/agents/${agentId}/credentials/${credentialId}`,
      token,
    });
  }
}
