//! Node services.
//!
//! Each service manages a specific aspect of the node.
#![allow(dead_code)]
#![allow(unused_imports)]

mod consensus;
mod contract;
mod governance;
mod mempool;
mod miner;
mod network;
mod rpc;
mod storage;
mod sync;

pub use consensus::ConsensusService;
pub use contract::ContractService;
pub use governance::{GovernanceError, GovernanceInfo, GovernanceService, TreasuryPoolInfo};
pub use mempool::MempoolService;
pub use miner::MinerService;
pub use network::NetworkService;
pub use rpc::RpcService;
pub use storage::{BlockData, StorageService};
pub use sync::SyncService;

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

    // ==================== Service Export Verification Tests ====================

    #[test]
    fn test_consensus_service_is_exported() {
        fn verify_type(_: &ConsensusService) {}
    }

    #[test]
    fn test_contract_service_is_exported() {
        fn verify_type(_: &ContractService) {}
    }

    #[test]
    fn test_governance_service_is_exported() {
        fn verify_type(_: &GovernanceService) {}
    }

    #[test]
    fn test_governance_error_is_exported() {
        fn verify_type(_: &GovernanceError) {}
    }

    #[test]
    fn test_governance_info_is_exported() {
        fn verify_type(_: &GovernanceInfo) {}
    }

    #[test]
    fn test_treasury_pool_info_is_exported() {
        fn verify_type(_: &TreasuryPoolInfo) {}
    }

    #[test]
    fn test_mempool_service_is_exported() {
        fn verify_type(_: &MempoolService) {}
    }

    #[test]
    fn test_miner_service_is_exported() {
        fn verify_type(_: &MinerService) {}
    }

    #[test]
    fn test_network_service_is_exported() {
        fn verify_type(_: &NetworkService) {}
    }

    #[test]
    fn test_rpc_service_is_exported() {
        fn verify_type(_: &RpcService) {}
    }

    #[test]
    fn test_storage_service_is_exported() {
        fn verify_type(_: &StorageService) {}
    }

    #[test]
    fn test_block_data_is_exported() {
        fn verify_type(_: &BlockData) {}
    }

    #[test]
    fn test_sync_service_is_exported() {
        fn verify_type(_: &SyncService) {}
    }

    // ==================== BlockData Tests ====================

    #[test]
    fn test_block_data_creation() {
        let block_data = BlockData {
            hash: [0u8; 32],
            header: vec![1, 2, 3, 4],
            body: vec![5, 6, 7, 8],
        };

        assert_eq!(block_data.hash, [0u8; 32]);
        assert_eq!(block_data.header, vec![1, 2, 3, 4]);
        assert_eq!(block_data.body, vec![5, 6, 7, 8]);
    }

    #[test]
    fn test_block_data_clone() {
        let original = BlockData {
            hash: [42u8; 32],
            header: vec![10, 20, 30],
            body: vec![40, 50, 60],
        };

        let cloned = original.clone();
        assert_eq!(cloned.hash, original.hash);
        assert_eq!(cloned.header, original.header);
        assert_eq!(cloned.body, original.body);
    }

    #[test]
    fn test_block_data_debug() {
        let block_data = BlockData {
            hash: [1u8; 32],
            header: vec![1, 2],
            body: vec![3, 4],
        };

        let debug_str = format!("{:?}", block_data);
        assert!(debug_str.contains("BlockData"));
        assert!(debug_str.contains("hash"));
        assert!(debug_str.contains("header"));
        assert!(debug_str.contains("body"));
    }

    #[test]
    fn test_block_data_with_empty_vectors() {
        let block_data = BlockData {
            hash: [0u8; 32],
            header: vec![],
            body: vec![],
        };

        assert!(block_data.header.is_empty());
        assert!(block_data.body.is_empty());
    }

    #[test]
    fn test_block_data_with_large_vectors() {
        let large_header = vec![0u8; 10_000];
        let large_body = vec![1u8; 100_000];

        let block_data = BlockData {
            hash: [255u8; 32],
            header: large_header.clone(),
            body: large_body.clone(),
        };

        assert_eq!(block_data.header.len(), 10_000);
        assert_eq!(block_data.body.len(), 100_000);
    }

    #[test]
    fn test_block_data_hash_uniqueness() {
        let data1 = BlockData {
            hash: [1u8; 32],
            header: vec![],
            body: vec![],
        };

        let data2 = BlockData {
            hash: [2u8; 32],
            header: vec![],
            body: vec![],
        };

        assert_ne!(data1.hash, data2.hash);
    }

    // ==================== Module Structure Tests ====================

    #[test]
    fn test_all_service_modules_are_included() {
        let _ = std::any::type_name::<ConsensusService>();
        let _ = std::any::type_name::<ContractService>();
        let _ = std::any::type_name::<GovernanceService>();
        let _ = std::any::type_name::<MempoolService>();
        let _ = std::any::type_name::<MinerService>();
        let _ = std::any::type_name::<NetworkService>();
        let _ = std::any::type_name::<RpcService>();
        let _ = std::any::type_name::<StorageService>();
        let _ = std::any::type_name::<SyncService>();
    }

    #[test]
    fn test_service_type_names_are_correct() {
        assert!(std::any::type_name::<ConsensusService>().contains("ConsensusService"));
        assert!(std::any::type_name::<ContractService>().contains("ContractService"));
        assert!(std::any::type_name::<GovernanceService>().contains("GovernanceService"));
        assert!(std::any::type_name::<MempoolService>().contains("MempoolService"));
        assert!(std::any::type_name::<MinerService>().contains("MinerService"));
        assert!(std::any::type_name::<NetworkService>().contains("NetworkService"));
        assert!(std::any::type_name::<RpcService>().contains("RpcService"));
        assert!(std::any::type_name::<StorageService>().contains("StorageService"));
        assert!(std::any::type_name::<SyncService>().contains("SyncService"));
    }

    // ==================== Re-export Completeness Tests ====================

    #[test]
    fn test_all_public_types_are_accessible_from_services_module() {
        use super::{
            BlockData, ConsensusService, ContractService, GovernanceError, GovernanceInfo,
            GovernanceService, MempoolService, MinerService, NetworkService, RpcService,
            StorageService, SyncService, TreasuryPoolInfo,
        };

        let _ = std::any::type_name::<BlockData>();
        let _ = std::any::type_name::<ConsensusService>();
        let _ = std::any::type_name::<ContractService>();
        let _ = std::any::type_name::<GovernanceError>();
        let _ = std::any::type_name::<GovernanceInfo>();
        let _ = std::any::type_name::<GovernanceService>();
        let _ = std::any::type_name::<MempoolService>();
        let _ = std::any::type_name::<MinerService>();
        let _ = std::any::type_name::<NetworkService>();
        let _ = std::any::type_name::<RpcService>();
        let _ = std::any::type_name::<StorageService>();
        let _ = std::any::type_name::<SyncService>();
        let _ = std::any::type_name::<TreasuryPoolInfo>();
    }

    // ==================== Service Count Verification ====================

    #[test]
    fn test_expected_number_of_core_services() {
        let service_count = 9;
        let services = [
            "consensus",
            "contract",
            "governance",
            "mempool",
            "miner",
            "network",
            "rpc",
            "storage",
            "sync",
        ];

        assert_eq!(services.len(), service_count);
    }

    // ==================== BlockData Serialization Tests ====================

    #[test]
    fn test_block_data_borsh_roundtrip() {
        use borsh::{BorshDeserialize, BorshSerialize};

        let original = BlockData {
            hash: [42u8; 32],
            header: vec![1, 2, 3, 4, 5],
            body: vec![6, 7, 8, 9, 10],
        };

        let serialized = borsh::to_vec(&original).unwrap();
        let deserialized: BlockData = BlockData::try_from_slice(&serialized).unwrap();

        assert_eq!(deserialized.hash, original.hash);
        assert_eq!(deserialized.header, original.header);
        assert_eq!(deserialized.body, original.body);
    }

    #[test]
    fn test_block_data_borsh_empty_roundtrip() {
        use borsh::{BorshDeserialize, BorshSerialize};

        let original = BlockData {
            hash: [0u8; 32],
            header: vec![],
            body: vec![],
        };

        let serialized = borsh::to_vec(&original).unwrap();
        let deserialized: BlockData = BlockData::try_from_slice(&serialized).unwrap();

        assert_eq!(deserialized.hash, original.hash);
        assert!(deserialized.header.is_empty());
        assert!(deserialized.body.is_empty());
    }

    #[test]
    fn test_block_data_borsh_serialization_size() {
        use borsh::BorshSerialize;

        let block_data = BlockData {
            hash: [0u8; 32],
            header: vec![0u8; 100],
            body: vec![0u8; 200],
        };

        let serialized = borsh::to_vec(&block_data).unwrap();
        // 32 bytes for hash + 4 bytes for header length + 100 bytes + 4 bytes for body length + 200 bytes
        assert_eq!(serialized.len(), 340);
    }

    // ==================== Hash Tests ====================

    #[test]
    fn test_block_data_hash_is_32_bytes() {
        let block_data = BlockData {
            hash: [0u8; 32],
            header: vec![],
            body: vec![],
        };

        assert_eq!(block_data.hash.len(), 32);
    }

    #[test]
    fn test_block_data_hash_all_zeros() {
        let block_data = BlockData {
            hash: [0u8; 32],
            header: vec![],
            body: vec![],
        };

        assert!(block_data.hash.iter().all(|&b| b == 0));
    }

    #[test]
    fn test_block_data_hash_all_ones() {
        let block_data = BlockData {
            hash: [255u8; 32],
            header: vec![],
            body: vec![],
        };

        assert!(block_data.hash.iter().all(|&b| b == 255));
    }

    #[test]
    fn test_block_data_hash_mixed_values() {
        let mut hash = [0u8; 32];
        for (i, byte) in hash.iter_mut().enumerate() {
            *byte = i as u8;
        }

        let block_data = BlockData {
            hash,
            header: vec![],
            body: vec![],
        };

        for (i, &byte) in block_data.hash.iter().enumerate() {
            assert_eq!(byte, i as u8);
        }
    }
}
