//! Credential management methods for `AgentIdPClient`.
//!
//! Covers `POST /agents/{id}/credentials` (generate),
//! `POST /agents/{id}/credentials/rotate`, and
//! `DELETE /agents/{id}/credentials/{cred_id}`.

use crate::agents::parse_response;
use crate::client::AgentIdPClient;
use crate::error::AgentIdPError;
use crate::models::Credentials;

impl AgentIdPClient {
    /// Generates a new set of credentials (client ID + secret) for an agent.
    ///
    /// `POST /agents/{id}/credentials` → `201 Credentials`
    ///
    /// The `client_secret` field in the response is the **only time** the
    /// plaintext secret is returned — store it securely.
    pub async fn generate_credentials(
        &self,
        agent_id: &str,
    ) -> Result<Credentials, AgentIdPError> {
        let auth = self.get_auth_header().await?;
        let url = format!("{}/agents/{}/credentials", self.base_url, agent_id);

        let resp = self
            .http
            .post(&url)
            .header("Authorization", auth)
            .header("Content-Length", "0")
            .send()
            .await?;

        parse_response(resp).await
    }

    /// Rotates the credentials for an agent, invalidating the previous secret.
    ///
    /// `POST /agents/{id}/credentials/rotate` → `200 Credentials`
    ///
    /// The new `client_secret` is returned in the response and will not be
    /// retrievable again.
    pub async fn rotate_credentials(
        &self,
        agent_id: &str,
    ) -> Result<Credentials, AgentIdPError> {
        let auth = self.get_auth_header().await?;
        let url = format!(
            "{}/agents/{}/credentials/rotate",
            self.base_url, agent_id
        );

        let resp = self
            .http
            .post(&url)
            .header("Authorization", auth)
            .header("Content-Length", "0")
            .send()
            .await?;

        parse_response(resp).await
    }

    /// Revokes a specific credential set for an agent.
    ///
    /// `DELETE /agents/{id}/credentials/{cred_id}` → `204 No Content`
    ///
    /// # Errors
    ///
    /// Returns [`crate::error::AgentIdPError::NotFound`] when the agent or
    /// credential ID does not exist.
    pub async fn revoke_credentials(
        &self,
        agent_id: &str,
        cred_id: &str,
    ) -> Result<(), AgentIdPError> {
        let auth = self.get_auth_header().await?;
        let url = format!(
            "{}/agents/{}/credentials/{}",
            self.base_url, agent_id, cred_id
        );

        let resp = self
            .http
            .delete(&url)
            .header("Authorization", auth)
            .send()
            .await?;

        if resp.status().as_u16() == 204 {
            return Ok(());
        }

        // Delegate error handling to parse_response; the Ok branch is unreachable.
        let _: Credentials = parse_response(resp).await?;
        Ok(())
    }
}
