//! Deployment status types.

use serde::{Deserialize, Serialize};

/// Status of a deployment.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeploymentStatus {
    /// Number of total replicas.
    pub replicas: i32,
    /// Number of ready replicas.
    pub ready_replicas: i32,
    /// Number of available replicas.
    pub available_replicas: i32,
    /// Number of updated replicas.
    pub updated_replicas: i32,
    /// Number of unavailable replicas.
    pub unavailable_replicas: i32,
    /// Generation number.
    pub observed_generation: Option<i64>,
}

impl DeploymentStatus {
    /// Check if the deployment is ready (all replicas are ready).
    pub fn is_ready(&self) -> bool {
        self.ready_replicas == self.replicas && self.replicas > 0
    }

    /// Check if the deployment is progressing.
    pub fn is_progressing(&self) -> bool {
        self.ready_replicas < self.replicas
    }

    /// Get the percentage of ready replicas.
    pub fn ready_percentage(&self) -> f64 {
        if self.replicas == 0 {
            return 0.0;
        }
        (self.ready_replicas as f64 / self.replicas as f64) * 100.0
    }
}

/// Phase of a pod.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PodPhase {
    /// Pod is pending.
    Pending,
    /// Pod is running.
    Running,
    /// Pod succeeded.
    Succeeded,
    /// Pod failed.
    Failed,
    /// Pod is in unknown state.
    Unknown,
}

impl PodPhase {
    /// Parse pod phase from string.
    pub fn parse(s: &str) -> Self {
        match s {
            "Pending" => PodPhase::Pending,
            "Running" => PodPhase::Running,
            "Succeeded" => PodPhase::Succeeded,
            "Failed" => PodPhase::Failed,
            _ => PodPhase::Unknown,
        }
    }

    /// Check if the phase indicates a terminal state.
    pub fn is_terminal(&self) -> bool {
        matches!(self, PodPhase::Succeeded | PodPhase::Failed)
    }

    /// Check if the phase indicates an error state.
    pub fn is_error(&self) -> bool {
        matches!(self, PodPhase::Failed | PodPhase::Unknown)
    }
}

/// Condition of a pod.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PodCondition {
    /// Type of condition.
    pub type_: String,
    /// Status of the condition (True, False, Unknown).
    pub status: String,
    /// Reason for the condition.
    pub reason: Option<String>,
    /// Human-readable message.
    pub message: Option<String>,
}

impl PodCondition {
    /// Check if the condition is true.
    pub fn is_true(&self) -> bool {
        self.status == "True"
    }

    /// Check if this is a "Ready" condition.
    pub fn is_ready_condition(&self) -> bool {
        self.type_ == "Ready"
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_deployment_status_is_ready() {
        let status = DeploymentStatus {
            replicas: 3,
            ready_replicas: 3,
            available_replicas: 3,
            updated_replicas: 3,
            unavailable_replicas: 0,
            observed_generation: Some(1),
        };
        assert!(status.is_ready());
        assert!(!status.is_progressing());
    }

    #[test]
    fn test_deployment_status_is_progressing() {
        let status = DeploymentStatus {
            replicas: 3,
            ready_replicas: 1,
            available_replicas: 1,
            updated_replicas: 2,
            unavailable_replicas: 2,
            observed_generation: Some(1),
        };
        assert!(!status.is_ready());
        assert!(status.is_progressing());
    }

    #[test]
    fn test_deployment_ready_percentage() {
        let status = DeploymentStatus {
            replicas: 4,
            ready_replicas: 2,
            available_replicas: 2,
            updated_replicas: 2,
            unavailable_replicas: 2,
            observed_generation: Some(1),
        };
        assert_eq!(status.ready_percentage(), 50.0);
    }

    #[test]
    fn test_pod_phase_parsing() {
        assert_eq!(PodPhase::parse("Running"), PodPhase::Running);
        assert_eq!(PodPhase::parse("Pending"), PodPhase::Pending);
        assert_eq!(PodPhase::parse("Failed"), PodPhase::Failed);
        assert_eq!(PodPhase::parse("Unknown"), PodPhase::Unknown);
        assert_eq!(PodPhase::parse("InvalidPhase"), PodPhase::Unknown);
    }

    #[test]
    fn test_pod_phase_states() {
        assert!(PodPhase::Failed.is_terminal());
        assert!(PodPhase::Succeeded.is_terminal());
        assert!(!PodPhase::Running.is_terminal());

        assert!(PodPhase::Failed.is_error());
        assert!(PodPhase::Unknown.is_error());
        assert!(!PodPhase::Running.is_error());
    }

    #[test]
    fn test_pod_condition() {
        let condition = PodCondition {
            type_: "Ready".to_string(),
            status: "True".to_string(),
            reason: None,
            message: None,
        };
        assert!(condition.is_true());
        assert!(condition.is_ready_condition());
    }
}
