//! Debates resource — adversarial multi-persona panel mode.

use futures::Stream;

use crate::client::Kranth;
use crate::errors::Result;
use crate::sse::stream_debate_events;
use crate::types::*;

pub struct DebatesResource<'a> {
    pub(crate) client: &'a Kranth,
}

impl<'a> DebatesResource<'a> {
    /// Create a new debate.
    pub async fn create(&self, req: &CreateDebateRequest) -> Result<DebateRow> {
        self.client.post("/v1/debates", req, None).await
    }

    /// Create a new debate with an idempotency key.
    pub async fn create_with_idempotency_key(
        &self,
        req: &CreateDebateRequest,
        idempotency_key: &str,
    ) -> Result<DebateRow> {
        self.client
            .post("/v1/debates", req, Some(idempotency_key))
            .await
    }

    /// Fetch a debate by id, including synthesis and audience reactions.
    pub async fn get(&self, debate_id: &str) -> Result<DebateDetail> {
        self.client
            .get(&format!("/v1/debates/{debate_id}"), &[])
            .await
    }

    /// List all debates for the org, along with speaker previews.
    pub async fn list(&self) -> Result<ListDebatesResponse> {
        self.client.get("/v1/debates", &[]).await
    }

    /// Fetch the ordered turn transcript for a debate.
    pub async fn turns(&self, debate_id: &str) -> Result<Vec<DebateTurn>> {
        #[derive(serde::Deserialize)]
        struct Wrap {
            turns: Vec<DebateTurn>,
        }
        let w: Wrap = self
            .client
            .get(&format!("/v1/debates/{debate_id}/turns"), &[])
            .await?;
        Ok(w.turns)
    }

    /// Toggle the public flag on a debate (PATCH). Returns updated detail.
    pub async fn set_public(&self, debate_id: &str, public: bool) -> Result<DebateDetail> {
        self.client
            .patch(
                &format!("/v1/debates/{debate_id}"),
                &serde_json::json!({ "public": public }),
            )
            .await
    }

    /// Cancel a running debate.
    pub async fn cancel(&self, debate_id: &str) -> Result<serde_json::Value> {
        self.client
            .post(
                &format!("/v1/debates/{debate_id}/cancel"),
                &serde_json::json!({}),
                None,
            )
            .await
    }

    /// Export a completed debate (returns raw JSON from the API).
    pub async fn export(&self, debate_id: &str) -> Result<serde_json::Value> {
        self.client
            .get(&format!("/v1/debates/{debate_id}/export"), &[])
            .await
    }

    /// Subscribe to the SSE event stream for a debate. Each item is a
    /// [`Result<DebateEvent>`]; the stream ends when the server closes the
    /// connection (typically after `debate.complete` or `debate.failed`).
    pub fn stream(&self, debate_id: &str) -> impl Stream<Item = Result<DebateEvent>> + 'a {
        stream_debate_events(self.client.clone(), debate_id.to_string())
    }
}
