//! Wire-shape types. Kept in lockstep with the api responses + the other
//! SDKs (sdks/python/src/kranth/_models.py, sdks/typescript/src/types.ts,
//! sdks/go/kranth.go).

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum SimStatus {
    Queued,
    Running,
    Complete,
    Failed,
    Canceled,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuthSource {
    ApiKey,
    Nexus,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelInfo {
    pub id: String,
    pub tier: String,
    pub display_name: String,
    pub provider: String,
    pub credits_per_100_personas: u32,
    pub plan_min: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Me {
    pub user_id: String,
    pub org_id: String,
    pub auth_source: AuthSource,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerdictReport {
    pub sentiment_score: f64,
    pub hostile_count: u32,
    pub aligned_count: u32,
    pub neutral_count: u32,
    pub themes: Vec<String>,
    pub top_objections: Vec<String>,
    pub representative_quotes: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimSummary {
    pub id: String,
    pub org_id: String,
    pub created_by: String,
    pub status: SimStatus,
    pub idea_text: String,
    pub persona_count: i32,
    pub personas_done: i32,
    pub model_tier: String,
    pub credits_charged: i32,
    pub avg_sentiment: Option<f64>,
    pub error_message: Option<String>,
    pub started_at: Option<String>,
    pub completed_at: Option<String>,
    pub created_at: String,
    #[serde(default)]
    pub report: Option<VerdictReport>,
}

#[derive(Debug, Clone, Serialize)]
pub struct CreateSimRequest {
    pub idea_text: String,
    pub persona_count: u32,
    pub model_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub training_opt_in: Option<bool>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct CreateSimResponse {
    pub sim_id: String,
    pub status: String,
    pub model_tier: String,
    pub credits_charged: u32,
    pub persona_count: u32,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListSimsResponse {
    pub sims: Vec<SimSummary>,
    pub next_cursor: Option<String>,
}

#[derive(Debug, Default, Clone)]
pub struct ListSimsParams {
    pub status: Option<String>,
    pub cursor: Option<String>,
    pub limit: Option<i64>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ApiKey {
    pub id: String,
    pub name: String,
    pub prefix: String,
    pub last_used_at: Option<String>,
    pub revoked_at: Option<String>,
    pub created_at: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct CreateApiKeyResponse {
    pub id: String,
    pub name: String,
    pub prefix: String,
    pub key: String,
    pub created_at: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Usage {
    pub plan: String,
    pub monthly_cap: i32,
    pub credits_consumed: i32,
    pub credits_remaining: i64,
    pub period_start: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct SimEvent {
    pub kind: String,
    pub sim_id: String,
    #[serde(default)]
    pub data: serde_json::Value,
}

// ─── Recon ─────────────────────────────────────────────────────

#[derive(Debug, Clone, Deserialize)]
pub struct CreateReconResponse {
    pub recon_id: String,
    pub status: String,
    pub tier: String,
    pub credits_charged: i64,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ReconTier {
    pub slug: String,
    pub label: String,
    pub worker_count: i32,
    pub price_credits: i32,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ReconSummary {
    pub id: String,
    pub status: String,
    pub idea_text: String,
    pub tier: String,
    pub score: Option<i32>,
    pub credits_charged: i64,
    pub created_at: String,
    pub completed_at: Option<String>,
    pub supported: i64,
    pub contradicted: i64,
    pub neutral: i64,
    #[serde(default)]
    pub source_domains: Vec<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ReconRun {
    pub id: String,
    pub status: String,
    pub idea_text: String,
    pub tier: String,
    pub score: Option<i32>,
    pub credits_charged: i64,
    pub created_at: String,
    pub completed_at: Option<String>,
    #[serde(default)]
    pub report: Option<serde_json::Value>,
    #[serde(default)]
    pub model_config: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ReconFinding {
    pub id: String,
    pub agent_role: String,
    pub claim: String,
    pub grounding: i16,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ReconSource {
    pub finding_id: Option<String>,
    pub url: String,
    pub title: String,
    pub snippet: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ReconDetail {
    pub run: ReconRun,
    #[serde(default)]
    pub findings: Vec<ReconFinding>,
    #[serde(default)]
    pub sources: Vec<ReconSource>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ReconEvent {
    pub kind: String,
    pub recon_id: String,
    #[serde(default)]
    pub data: serde_json::Value,
}

#[derive(Debug, Clone, Serialize)]
pub struct CreateReconRequest {
    pub idea_text: String,
    pub tier: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub worker_model: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub synth_model: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub audience: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub company_url: Option<String>,
}

// ─── Debates ───────────────────────────────────────────────────

#[derive(Debug, Clone, Deserialize)]
pub struct DebateRow {
    pub id: String,
    pub topic: String,
    pub mode: String,
    pub status: String,
    pub participants: i32,
    pub max_turns: i32,
    pub duration_secs: i32,
    pub model_id: String,
    pub error_message: Option<String>,
    pub started_at: Option<String>,
    pub completed_at: Option<String>,
    pub created_at: String,
    pub public: bool,
    #[serde(default)]
    pub turn_count: i64,
    pub voice_enabled: bool,
    pub score: Option<i32>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct SpeakerPreview {
    pub speaker_name: String,
    pub speaker_username: String,
    pub speaker_archetype: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListDebatesResponse {
    pub debates: Vec<DebateRow>,
    #[serde(default)]
    pub speakers: std::collections::HashMap<String, Vec<SpeakerPreview>>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DebateTurn {
    pub speaker_id: String,
    pub speaker_archetype: String,
    pub speaker_name: String,
    pub speaker_username: String,
    pub role: String,
    pub body: String,
    pub emitted_at: String,
    pub audio_url: Option<String>,
    pub audio_voice_id: Option<String>,
    pub audio_ms: Option<i32>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DebateSynthesis {
    pub score: i32,
    pub pct_for: i32,
    pub pct_against: i32,
    pub pct_undecided: i32,
    pub verdict_reasons: Vec<String>,
    pub decisive_argument: String,
    pub top_unrebutted: String,
    pub summary: String,
    pub key_arguments: Vec<String>,
    pub key_objections: Vec<String>,
    pub common_ground: Vec<String>,
    pub strongest_turn: String,
    pub model_id: String,
    pub created_at: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct AudienceReaction {
    pub persona_id: String,
    pub speaker_name: String,
    pub archetype: String,
    pub body: String,
    pub sentiment: f64,
    pub sentiment_label: String,
    pub turn_seq: i32,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DebateDetail {
    #[serde(flatten)]
    pub debate: DebateRow,
    pub synthesis: Option<DebateSynthesis>,
    #[serde(default)]
    pub audience: Vec<AudienceReaction>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DebateEvent {
    pub kind: String,
    pub debate_id: String,
    #[serde(default)]
    pub data: serde_json::Value,
}

#[derive(Debug, Clone, Serialize)]
pub struct CreateDebateRequest {
    pub topic: String,
    pub mode: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub participants: Option<i32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub model_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub training_opt_in: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub public: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub voice_enabled: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub archetype_slugs: Option<Vec<String>>,
}
