//! Directive API methods.

use uuid::Uuid;

use super::client::{ApiClient, ApiError};
use super::supervisor::JsonValue;

impl ApiClient {
    /// Create a new directive.
    pub async fn create_directive(
        &self,
        goal: &str,
        repository_url: Option<&str>,
        autonomy_level: &str,
    ) -> Result<JsonValue, ApiError> {
        #[derive(serde::Serialize)]
        #[serde(rename_all = "camelCase")]
        struct CreateRequest<'a> {
            goal: &'a str,
            repository_url: Option<&'a str>,
            autonomy_level: &'a str,
        }
        let req = CreateRequest {
            goal,
            repository_url,
            autonomy_level,
        };
        self.post("/api/v1/directives", &req).await
    }

    /// List all directives for the authenticated user.
    pub async fn list_directives(
        &self,
        status: Option<&str>,
        limit: i32,
    ) -> Result<JsonValue, ApiError> {
        let mut params = Vec::new();
        if let Some(s) = status {
            params.push(format!("status={}", s));
        }
        params.push(format!("limit={}", limit));
        let query_string = format!("?{}", params.join("&"));
        self.get(&format!("/api/v1/directives{}", query_string))
            .await
    }

    /// Get a directive by ID (includes progress info).
    pub async fn get_directive(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.get(&format!("/api/v1/directives/{}", directive_id))
            .await
    }

    /// Archive a directive.
    pub async fn archive_directive(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.delete_with_response(&format!("/api/v1/directives/{}", directive_id))
            .await
    }

    /// Start a directive (plans and begins execution).
    pub async fn start_directive(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.post_empty(&format!("/api/v1/directives/{}/start", directive_id))
            .await
    }

    /// Pause a directive.
    pub async fn pause_directive(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.post_empty(&format!("/api/v1/directives/{}/pause", directive_id))
            .await
    }

    /// Resume a paused directive.
    pub async fn resume_directive(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.post_empty(&format!("/api/v1/directives/{}/resume", directive_id))
            .await
    }

    /// Stop a directive.
    pub async fn stop_directive(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.post_empty(&format!("/api/v1/directives/{}/stop", directive_id))
            .await
    }

    /// Get the current chain and steps for a directive.
    pub async fn get_directive_chain(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.get(&format!("/api/v1/directives/{}/chain", directive_id))
            .await
    }

    /// Get directive DAG structure for visualization.
    pub async fn get_directive_graph(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> {
        self.get(&format!("/api/v1/directives/{}/chain/graph", directive_id))
            .await
    }

    /// List events for a directive.
    pub async fn list_directive_events(
        &self,
        directive_id: Uuid,
        limit: i32,
    ) -> Result<JsonValue, ApiError> {
        self.get(&format!(
            "/api/v1/directives/{}/events?limit={}",
            directive_id, limit
        ))
        .await
    }

    /// List pending approvals for a directive.
    pub async fn list_directive_approvals(
        &self,
        directive_id: Uuid,
    ) -> Result<JsonValue, ApiError> {
        self.get(&format!("/api/v1/directives/{}/approvals", directive_id))
            .await
    }

    /// Approve an approval request.
    pub async fn approve_directive_request(
        &self,
        directive_id: Uuid,
        approval_id: Uuid,
        response: Option<&str>,
    ) -> Result<JsonValue, ApiError> {
        #[derive(serde::Serialize)]
        #[serde(rename_all = "camelCase")]
        struct ApprovalRequest<'a> {
            response: Option<&'a str>,
        }
        let req = ApprovalRequest { response };
        self.post(
            &format!(
                "/api/v1/directives/{}/approvals/{}/approve",
                directive_id, approval_id
            ),
            &req,
        )
        .await
    }

    /// Deny an approval request.
    pub async fn deny_directive_request(
        &self,
        directive_id: Uuid,
        approval_id: Uuid,
        response: Option<&str>,
    ) -> Result<JsonValue, ApiError> {
        #[derive(serde::Serialize)]
        #[serde(rename_all = "camelCase")]
        struct ApprovalRequest<'a> {
            response: Option<&'a str>,
        }
        let req = ApprovalRequest { response };
        self.post(
            &format!(
                "/api/v1/directives/{}/approvals/{}/deny",
                directive_id, approval_id
            ),
            &req,
        )
        .await
    }
}
