use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct ProgramId(pub String);

impl std::fmt::Display for ProgramId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl From<String> for ProgramId {
    fn from(s: String) -> Self {
        ProgramId(s)
    }
}

impl From<&str> for ProgramId {
    fn from(s: &str) -> Self {
        ProgramId(s.to_string())
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgramStatus {
    pub program_id: ProgramId,
    pub version_hash: String,
    pub state: ProgramState,
    pub pid: Option<u32>,
    pub uptime_secs: Option<u64>,
    pub restart_count: u32,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ProgramState {
    Downloading,
    Building,
    Starting,
    Running,
    Stopping,
    Stopped,
    Crashed,
    Failed,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgramSummary {
    pub program_id: ProgramId,
    pub version_hash: String,
    pub agents: ProgramAgentStats,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgramAgentStats {
    pub deployed: usize,
    pub running: usize,
    pub building: usize,
    pub failed: usize,
}
