use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum HarnessKind {
    Claude,
    Codex,
    OpenClaw,
    Generic,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct HarnessConfig {
    pub name: String,
    pub kind: HarnessKind,
    pub command: String,
    #[serde(default)]
    pub args: Vec<String>,
    pub cwd: String,
    pub personality: String,
    #[serde(default)]
    pub env: Vec<(String, String)>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct HarnessInfo {
    pub id: String,
    pub name: String,
    pub kind: HarnessKind,
    pub cwd: String,
    pub personality: String,
    pub pid: Option<u32>,
    pub alive: bool,
    pub log_path: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Message {
    pub from: String,
    pub to: String,
    pub body: String,
    pub at_unix_ms: u64,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum EventStream {
    Stdin,
    Stdout,
    Stderr,
    Status,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct HarnessEvent {
    pub harness: String,
    pub stream: EventStream,
    pub line: String,
    pub at_unix_ms: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Request {
    Ping,
    Register {
        config: HarnessConfig,
    },
    Spawn {
        name: String,
    },
    Ensure {
        config: HarnessConfig,
    },
    List,
    Ask {
        from: String,
        to: String,
        body: String,
    },
    Messages {
        name: String,
    },
    Events {
        name: String,
        max: usize,
    },
    InjectMcp {
        cwd: String,
        server_name: String,
    },
    Stop {
        name: String,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Response {
    Pong,
    Registered { id: String },
    Spawned { info: HarnessInfo },
    List { harnesses: Vec<HarnessInfo> },
    Asked { message: Message },
    Messages { messages: Vec<Message> },
    Events { events: Vec<HarnessEvent> },
    InjectedMcp { path: String, server_name: String },
    Stopped { name: String },
    Error { message: String },
}
