use stemedb_admin::{output, types};

#[test]
fn test_output_format_parsing() {
    use std::str::FromStr;
    use stemedb_admin::output::OutputFormat;

    let table = OutputFormat::from_str("table").expect("Failed to parse 'table'");
    assert_eq!(table, OutputFormat::Table);

    let json = OutputFormat::from_str("json").expect("Failed to parse 'json'");
    assert_eq!(json, OutputFormat::Json);

    let invalid = OutputFormat::from_str("invalid");
    assert!(invalid.is_err());
}

#[test]
fn test_cluster_status_json_serialization() {
    let status = types::ClusterStatusResponse {
        node_count: 3,
        shard_count: 32,
        meta_version: 158,
        nodes: vec![
            types::NodeStatusInfo {
                id: "a3f2b1c4".to_string(),
                state: "Alive".to_string(),
                shards: vec![1, 2, 3],
            },
            types::NodeStatusInfo {
                id: "7d8e9f0a".to_string(),
                state: "Dead".to_string(),
                shards: vec![4, 5],
            },
        ],
    };

    let json = output::format_json(&status).expect("Failed to format as JSON");
    assert!(json.contains("\"node_count\": 3"));
    assert!(json.contains("\"shard_count\": 32"));
    assert!(json.contains("\"a3f2b1c4\""));

    // Verify it's valid JSON
    let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON produced");
    assert_eq!(parsed["node_count"], 3);
    assert_eq!(parsed["shard_count"], 32);
}

#[test]
fn test_health_response_json_serialization() {
    let health = types::HealthResponse { healthy: true, reachable_nodes: 3, joined: true };

    let json = output::format_json(&health).expect("Failed to format as JSON");
    assert!(json.contains("\"healthy\": true"));
    assert!(json.contains("\"reachable_nodes\": 3"));

    // Verify it's valid JSON
    let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON produced");
    assert_eq!(parsed["healthy"], true);
    assert_eq!(parsed["reachable_nodes"], 3);
}

#[test]
fn test_range_info_json_serialization() {
    let range = types::RangeInfoDto {
        range_id: 5,
        start_key: "".to_string(),
        end_key: "m".to_string(),
        size_bytes: 1_048_576, // 1 MB
        assertion_count: 1000,
        leader_node: "a3f2b1c4".to_string(),
        replica_nodes: vec!["7d8e9f0a".to_string(), "b1c2d3e4".to_string()],
        generation: 10,
    };

    let json = output::format_json(&range).expect("Failed to format as JSON");
    assert!(json.contains("\"range_id\": 5"));
    assert!(json.contains("\"assertion_count\": 1000"));

    // Verify it's valid JSON
    let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON produced");
    assert_eq!(parsed["range_id"], 5);
    assert_eq!(parsed["assertion_count"], 1000);
}

#[test]
fn test_nodes_table_formatting() {
    let nodes = vec![
        types::NodeStatusInfo {
            id: "a3f2b1c4".to_string(),
            state: "Alive".to_string(),
            shards: vec![1, 2, 3],
        },
        types::NodeStatusInfo {
            id: "7d8e9f0a".to_string(),
            state: "Dead".to_string(),
            shards: vec![4, 5, 6, 7, 8, 9],
        },
    ];

    let table = output::format_nodes_table(&nodes);
    assert!(table.contains("a3f2b1c4"));
    assert!(table.contains("7d8e9f0a"));
    assert!(table.contains("Alive") || table.contains("Dead")); // Color codes may be present
}

#[test]
fn test_shards_table_formatting() {
    let shards = vec![
        types::RangeInfoDto {
            range_id: 1,
            start_key: "".to_string(),
            end_key: "m".to_string(),
            size_bytes: 2_097_152, // 2 MB
            assertion_count: 5000,
            leader_node: "a3f2b1c4".to_string(),
            replica_nodes: vec!["7d8e9f0a".to_string()],
            generation: 5,
        },
        types::RangeInfoDto {
            range_id: 2,
            start_key: "m".to_string(),
            end_key: "z".to_string(),
            size_bytes: 1_048_576, // 1 MB
            assertion_count: 2500,
            leader_node: "7d8e9f0a".to_string(),
            replica_nodes: vec!["a3f2b1c4".to_string()],
            generation: 5,
        },
    ];

    let table = output::format_shards_table(&shards);
    assert!(table.contains("a3f2b1c4"));
    assert!(table.contains("7d8e9f0a"));
}

#[test]
fn test_cluster_summary_formatting() {
    let status = types::ClusterStatusResponse {
        node_count: 3,
        shard_count: 32,
        meta_version: 158,
        nodes: vec![types::NodeStatusInfo {
            id: "a3f2b1c4".to_string(),
            state: "Alive".to_string(),
            shards: vec![1, 2, 3],
        }],
    };

    let summary = output::format_cluster_summary(&status);
    assert!(summary.contains("Node Count:    3"));
    assert!(summary.contains("Shard Count:   32"));
    assert!(summary.contains("Meta Version:  158"));
}

#[test]
fn test_debug_export_structure() {
    let export = types::ClusterDebugExport {
        timestamp: "2026-02-12T10:30:00Z".to_string(),
        gateway_version: "0.1.0".to_string(),
        cluster: types::ClusterStatusResponse {
            node_count: 3,
            shard_count: 32,
            meta_version: 158,
            nodes: vec![],
        },
        health: types::HealthResponse { healthy: true, reachable_nodes: 3, joined: true },
        shards: vec![],
    };

    let json = output::format_json(&export).expect("Failed to format debug export");
    assert!(json.contains("\"timestamp\""));
    assert!(json.contains("\"gateway_version\""));
    assert!(json.contains("\"cluster\""));
    assert!(json.contains("\"health\""));
    assert!(json.contains("\"shards\""));
}

#[test]
fn test_empty_nodes_table() {
    let nodes: Vec<types::NodeStatusInfo> = vec![];
    let table = output::format_nodes_table(&nodes);
    assert!(table.contains("(no nodes)"));
}

#[test]
fn test_empty_shards_table() {
    let shards: Vec<types::RangeInfoDto> = vec![];
    let table = output::format_shards_table(&shards);
    assert!(table.contains("(no shards)"));
}
