// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};

/// Validator health status enumeration for validator health checks
/// This follows the Solana RPC validator health specification:
/// - "ok" when the validator is healthy and operating normally
/// - "unhealthy" when the validator is experiencing issues
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum ValidatorHealthStatus {
    /// Validator is healthy and operating normally
    #[default]
    Ok,
    /// Validator is unhealthy or experiencing issues
    Unhealthy,
}

impl ValidatorHealthStatus {
    /// Create a healthy validator status
    pub fn ok() -> Self {
        Self::Ok
    }

    /// Create an unhealthy validator status
    pub fn unhealthy() -> Self {
        Self::Unhealthy
    }
}

/// The response message for a getValidatorHealth request.
/// Returns the current health status of the validator.
#[derive(Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct GetValidatorHealthResponse {
    /// Validator health status
    pub status: ValidatorHealthStatus,
}

impl GetValidatorHealthResponse {
    pub fn new(status: ValidatorHealthStatus) -> Self {
        Self { status }
    }

    pub fn ok() -> Self {
        Self::new(ValidatorHealthStatus::Ok)
    }

    pub fn unhealthy() -> Self {
        Self::new(ValidatorHealthStatus::Unhealthy)
    }
}

/// Request for getValidatorHealth RPC call
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct GetValidatorHealthRequest {
    // Empty parameters - this method takes no arguments
}

impl GetValidatorHealthRequest {
    pub fn new() -> Self {
        Self {}
    }
}

impl Default for GetValidatorHealthRequest {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use serde_json::{from_str, to_string};

    use super::*;

    #[test]
    fn test_validator_health_status_ok_serialization() {
        let status = ValidatorHealthStatus::Ok;
        let json = to_string(&status).unwrap();
        assert_eq!(json, "\"ok\"");

        let deserialized: ValidatorHealthStatus = from_str(&json).unwrap();
        assert_eq!(deserialized, ValidatorHealthStatus::Ok);
    }

    #[test]
    fn test_validator_health_status_unhealthy_serialization() {
        let status = ValidatorHealthStatus::Unhealthy;
        let json = to_string(&status).unwrap();
        assert_eq!(json, "\"unhealthy\"");

        let deserialized: ValidatorHealthStatus = from_str(&json).unwrap();
        assert_eq!(deserialized, ValidatorHealthStatus::Unhealthy);
    }

    #[test]
    fn test_get_validator_health_response_ok_serialization() {
        let response = GetValidatorHealthResponse::ok();
        let json = to_string(&response).unwrap();
        assert_eq!(json, "\"ok\"");

        let deserialized: GetValidatorHealthResponse = from_str(&json).unwrap();
        assert_eq!(deserialized.status, ValidatorHealthStatus::Ok);
    }

    #[test]
    fn test_get_validator_health_response_unhealthy_serialization() {
        let response = GetValidatorHealthResponse::unhealthy();
        let json = to_string(&response).unwrap();
        assert_eq!(json, "\"unhealthy\"");

        let deserialized: GetValidatorHealthResponse = from_str(&json).unwrap();
        assert_eq!(deserialized.status, ValidatorHealthStatus::Unhealthy);
    }

    #[test]
    fn test_validator_health_status_default() {
        let status = ValidatorHealthStatus::default();
        assert_eq!(status, ValidatorHealthStatus::Ok);
    }
}
