//! Agent registration and lifecycle operations.

use crate::zeroid::{
    client::{parse_api_error, ZeroIDClient},
    error::ZeroIDError,
    types::{AgentList, AgentRegistered, AgentResponse, RegisterAgentRequest, UpdateAgentRequest},
};

/// Agents resource — registration, CRUD, and lifecycle on `/api/v1/agents`.
pub struct AgentsResource<'a> {
    pub(crate) client: &'a ZeroIDClient,
}

impl<'a> AgentsResource<'a> {
    /// Register a new agent (creates identity + API key atomically).
    ///
    /// `POST /api/v1/agents/register`
    pub async fn register(
        &self,
        request: &RegisterAgentRequest,
    ) -> Result<AgentRegistered, ZeroIDError> {
        let body = serde_json::to_value(request)?;
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(
                reqwest::Method::POST,
                "/api/v1/agents/register",
                headers,
                Some(&body),
            )
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }

    /// Get an agent by identity ID.
    ///
    /// `GET /api/v1/agents/registry/{id}`
    pub async fn get(&self, id: &str) -> Result<AgentResponse, ZeroIDError> {
        let path = format!("/api/v1/agents/registry/{id}");
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(reqwest::Method::GET, &path, headers, None)
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }

    /// List agents for the current tenant.
    ///
    /// `GET /api/v1/agents/registry`
    pub async fn list(&self) -> Result<AgentList, ZeroIDError> {
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(
                reqwest::Method::GET,
                "/api/v1/agents/registry",
                headers,
                None,
            )
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }

    /// Update mutable fields of an agent.
    ///
    /// `PATCH /api/v1/agents/registry/{id}`
    pub async fn update(
        &self,
        id: &str,
        request: &UpdateAgentRequest,
    ) -> Result<AgentResponse, ZeroIDError> {
        let path = format!("/api/v1/agents/registry/{id}");
        let body = serde_json::to_value(request)?;
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(reqwest::Method::PATCH, &path, headers, Some(&body))
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }

    /// Deactivate an agent (soft delete) and revoke its keys.
    ///
    /// `DELETE /api/v1/agents/registry/{id}`
    pub async fn delete(&self, id: &str) -> Result<AgentResponse, ZeroIDError> {
        let path = format!("/api/v1/agents/registry/{id}");
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(reqwest::Method::DELETE, &path, headers, None)
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }

    /// Activate a previously deactivated agent.
    ///
    /// `POST /api/v1/agents/registry/{id}/activate`
    pub async fn activate(&self, id: &str) -> Result<AgentResponse, ZeroIDError> {
        let path = format!("/api/v1/agents/registry/{id}/activate");
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(reqwest::Method::POST, &path, headers, None)
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }

    /// Deactivate an agent without deleting it.
    ///
    /// `POST /api/v1/agents/registry/{id}/deactivate`
    pub async fn deactivate(&self, id: &str) -> Result<AgentResponse, ZeroIDError> {
        let path = format!("/api/v1/agents/registry/{id}/deactivate");
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(reqwest::Method::POST, &path, headers, None)
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }

    /// Rotate an agent's API key (revokes old, issues new).
    ///
    /// `POST /api/v1/agents/registry/{id}/rotate-key`
    pub async fn rotate_key(&self, id: &str) -> Result<AgentRegistered, ZeroIDError> {
        let path = format!("/api/v1/agents/registry/{id}/rotate-key");
        let headers = self.client.admin_headers();
        let resp = self
            .client
            .send_with_retry(reqwest::Method::POST, &path, headers, None)
            .await?;
        if !resp.status().is_success() {
            return Err(parse_api_error(resp).await);
        }
        Ok(resp.json().await?)
    }
}
