use core_types::Timestamp;
use introspection_core::{
    ActionStatus, DiscoveryLoadCounts, GraphEdge, HealthStatusItem, MiddlewareLoadReport,
    MiddlewareLoadTotals, MissionStatus, NodeStatus, PluginStatus, ResourceCatalogReport,
    RuntimeHealthView, RuntimeLoadReport, RuntimeMetricView, ServiceLoadView, ServiceStatus,
    SessionLifecycleLoadCounts, StatusSnapshot, TopicAckSummary, TopicLoadView, TopicStatus,
};

pub fn demo_status_snapshot() -> StatusSnapshot {
    StatusSnapshot::new(
        vec![NodeStatus {
            name: "demo_node".to_string(),
            namespace: "/demo".to_string(),
            capabilities: vec![
                "pubsub".to_string(),
                "service".to_string(),
                "mission".to_string(),
            ],
        }],
        vec![TopicStatus {
            name: "/demo/camera/raw".to_string(),
            schema: "sample.image".to_string(),
            reliable: true,
            depth: 16,
            pending: 3,
            max_depth: 16,
            publishers: 1,
            subscribers: 1,
            reliable_local_ack: TopicAckSummary::default(),
            reliable_remote_ack: TopicAckSummary::default(),
        }],
        vec![ServiceStatus {
            name: "/demo/echo".to_string(),
            pending_requests: 1,
            pending_responses: 0,
            clients: 1,
            servers: 1,
        }],
        vec![ActionStatus {
            name: "/demo/calibrate".to_string(),
            clients: 1,
            servers: 1,
            current_state: Some("executing".to_string()),
            active_goals: Some(1),
            health_state: Some("active".to_string()),
            heartbeat_timeout_ms: Some(5000),
            last_heartbeat_at_unix_nanos: Some(Timestamp::now().0),
            last_feedback_at_unix_nanos: Some(Timestamp::now().0),
            last_result_at_unix_nanos: None,
        }],
        vec![MissionStatus {
            name: "demo_mission".to_string(),
            state: "running".to_string(),
            last_checkpoint: Some("cp-demo-1".to_string()),
        }],
        vec![
            HealthStatusItem {
                component: "runtime".to_string(),
                status: "healthy".to_string(),
                reason: None,
            },
            HealthStatusItem {
                component: "device".to_string(),
                status: "healthy".to_string(),
                reason: None,
            },
            HealthStatusItem {
                component: "pipeline".to_string(),
                status: "healthy".to_string(),
                reason: None,
            },
            HealthStatusItem {
                component: "plugin".to_string(),
                status: "healthy".to_string(),
                reason: None,
            },
        ],
        vec![
            PluginStatus {
                name: "sample-device-plugin".to_string(),
                kind: "device".to_string(),
                loaded: true,
            },
            PluginStatus {
                name: "sample-obs-plugin".to_string(),
                kind: "observability".to_string(),
                loaded: false,
            },
        ],
        vec![
            GraphEdge {
                from: "demo_node".to_string(),
                to: "/demo/camera/raw".to_string(),
                relation: "publishes".to_string(),
            },
            GraphEdge {
                from: "demo_node".to_string(),
                to: "/demo/echo".to_string(),
                relation: "provides".to_string(),
            },
        ],
    )
}

pub fn demo_runtime_report() -> RuntimeLoadReport {
    let snapshot = demo_status_snapshot();
    let queue_depth = snapshot.topics.iter().map(|topic| topic.pending as u64).sum();
    RuntimeLoadReport {
        queue_depth: Some(queue_depth),
        retransmit_drivers: Some(0),
        backpressure: Some(0.0),
        health: RuntimeHealthView {
            status: String::from("healthy"),
            reason: None,
        },
        metrics: vec![
            RuntimeMetricView {
                name: String::from("runtime.queue_depth"),
                value: queue_depth as f64,
                unit: String::new(),
            },
            RuntimeMetricView {
                name: String::from("runtime.backpressure"),
                value: 0.0,
                unit: String::new(),
            },
        ],
    }
}

pub fn demo_middleware_report() -> MiddlewareLoadReport {
    let snapshot = demo_status_snapshot();
    let topics = snapshot
        .topics
        .iter()
        .map(|topic| TopicLoadView {
            topic: topic.name.clone(),
            pending: topic.pending,
            max_depth: topic.max_depth,
            utilization_ratio: if topic.max_depth == 0 {
                0.0
            } else {
                topic.pending as f64 / topic.max_depth as f64
            },
            dropped_messages: 0,
            lag_messages: 0,
            retry_inflight: 0,
            replay_attempts: 0,
            degraded_subscribers: 0,
        })
        .collect::<Vec<_>>();
    let services = snapshot
        .services
        .iter()
        .map(|service| ServiceLoadView {
            service: service.name.clone(),
            pending_requests: service.pending_requests,
            pending_responses: service.pending_responses,
        })
        .collect::<Vec<_>>();

    MiddlewareLoadReport {
        captured_at_unix_nanos: Timestamp::now().0,
        discovery: DiscoveryLoadCounts {
            topics: topics.len(),
            services: services.len(),
            missions: snapshot.missions.len(),
        },
        sessions: SessionLifecycleLoadCounts::default(),
        totals: MiddlewareLoadTotals {
            topic_count: topics.len(),
            topic_pending_total: topics.iter().map(|topic| topic.pending).sum(),
            service_count: services.len(),
            service_pending_requests_total: services
                .iter()
                .map(|service| service.pending_requests)
                .sum(),
            service_pending_responses_total: services
                .iter()
                .map(|service| service.pending_responses)
                .sum(),
        },
        topics,
        services,
    }
}

pub fn demo_resource_report() -> ResourceCatalogReport {
    let snapshot = demo_status_snapshot();
    ResourceCatalogReport::from_lists(
        snapshot
            .nodes
            .iter()
            .map(|node| format!("{}/{}", node.namespace.trim_end_matches('/'), node.name))
            .collect(),
        snapshot
            .topics
            .iter()
            .map(|topic| topic.name.clone())
            .collect(),
        snapshot
            .services
            .iter()
            .map(|service| service.name.clone())
            .collect(),
        snapshot
            .actions
            .iter()
            .map(|action| action.name.clone())
            .collect(),
        snapshot
            .missions
            .iter()
            .map(|mission| mission.name.clone())
            .collect(),
    )
}
