/// Demonstration of OnionCoin's Proof-of-Contribution consensus
///
/// Shows how validators earn rewards through:
/// - Stake (40%)
/// - Tor relay work (30%) ← UNIQUE!
/// - Bandwidth (15%)
/// - Uptime (10%)
/// - Storage (5%)

use onioncoin_consensus::*;
use onioncoin_consensus::proof_of_contribution::ScoreWeights;

fn main() {
    println!("=== OnionCoin Proof-of-Contribution Demo ===\n");

    demo_validator_tiers();
    println!();

    demo_contribution_scoring();
    println!();

    demo_relay_proof();
    println!();

    demo_validator_selection();
    println!();

    demo_genesis_mining();
}

fn demo_validator_tiers() {
    println!("🎯 VALIDATOR TIERS");
    println!("==================");

    let tiers = [
        ValidatorTier::Micro,
        ValidatorTier::Light,
        ValidatorTier::Standard,
        ValidatorTier::Power,
    ];

    println!("┌─────────────┬──────────────┬────────────────────┬──────────────────┐");
    println!("│ Tier        │ Min Stake    │ Hardware           │ Monthly Return   │");
    println!("├─────────────┼──────────────┼────────────────────┼──────────────────┤");

    for tier in &tiers {
        println!(
            "│ {:11} │ {:10} ONC │ {:18} │ ~{:13} ONC │",
            format!("{:?}", tier),
            tier.min_stake(),
            match tier {
                ValidatorTier::Micro => "Raspberry Pi Zero",
                ValidatorTier::Light => "Raspberry Pi 4",
                ValidatorTier::Standard => "Desktop PC/VPS",
                ValidatorTier::Power => "Server 24/7",
            },
            format!("{:.1}", tier.expected_monthly_return())
        );
    }

    println!("└─────────────┴──────────────┴────────────────────┴──────────────────┘");
    println!("\n✅ Even a Raspberry Pi Zero can validate!");
}

fn demo_contribution_scoring() {
    println!("📊 CONTRIBUTION SCORING");
    println!("======================");

    // Scenario 1: Whale with just stake (lazy validator)
    let whale = Validator::new([1u8; 32], 10000, "whale.onion".to_string(), 0).unwrap();
    let whale_score = ProofOfContribution::calculate(
        &whale,
        None, // No relay work
        &BandwidthMetrics::new(),
        &UptimeMetrics::new(0),
        &StorageMetrics::new(),
    );

    println!("Scenario 1: Whale Validator (10,000 ONC stake, no work)");
    println!("{}", whale_score.score.breakdown());

    println!("\n─────────────────────────────────────────────────────\n");

    // Scenario 2: Micro validator with relay work (active participant)
    let micro = Validator::new([2u8; 32], 10, "micro.onion".to_string(), 0).unwrap();

    // Excellent relay metrics
    let mut relay_metrics = RelayMetrics::new();
    relay_metrics.bytes_relayed = 100 * 1024 * 1024 * 1024; // 100 GB!
    relay_metrics.unique_circuits = 200;
    relay_metrics.packets_relayed = 1_000_000;
    relay_metrics.avg_latency_ms = 500;

    let relay_proof = RelayProof::new([2u8; 32], 0, 3600, relay_metrics);

    // Good bandwidth
    let mut bandwidth = BandwidthMetrics::new();
    bandwidth.update(10_000_000, 10_000_000, 100);

    // Great uptime
    let mut uptime = UptimeMetrics::new(0);
    for i in 1..=1000 {
        uptime.record_heartbeat(i * 60);
    }

    // Some storage
    let mut storage = StorageMetrics::new();
    storage.update(20 * 1024 * 1024 * 1024, 10 * 1024 * 1024 * 1024, 1000, 10000);

    let micro_score = ProofOfContribution::calculate(
        &micro,
        Some(&relay_proof),
        &bandwidth,
        &uptime,
        &storage,
    );

    println!("Scenario 2: Micro Validator (10 ONC stake, LOTS of work)");
    println!("{}", micro_score.score.breakdown());

    println!("\n🎯 KEY INSIGHT:");
    println!("   Whale total score: {:.3}", whale_score.total_score());
    println!("   Micro total score: {:.3}", micro_score.total_score());
    println!("\n   Micro validator is {}% as competitive as whale!",
        (micro_score.total_score() / whale_score.total_score() * 100.0) as i32);
    println!("   💡 OnionCoin rewards WORK, not just wealth!");
}

fn demo_relay_proof() {
    println!("🌐 PROOF-OF-RELAY (OnionCoin's UNIQUE Feature)");
    println!("==============================================");

    println!("Relay Node Activity:");
    println!("  - Relayed: 50 GB of OnionCoin traffic");
    println!("  - Circuits: 150 unique Tor circuits");
    println!("  - Packets: 500,000");
    println!("  - Latency: 800ms average");

    let mut metrics = RelayMetrics::new();
    metrics.bytes_relayed = 50 * 1024 * 1024 * 1024;
    metrics.unique_circuits = 150;
    metrics.packets_relayed = 500_000;
    metrics.avg_latency_ms = 800;

    let proof = RelayProof::new([42u8; 32], 0, 3600, metrics);

    println!("\nRelay Proof:");
    println!("  - Valid: {}", proof.verify());
    println!("  - Quality Score: {:.2}", proof.metrics.quality_score());
    println!("  - Reward: {} ONC", proof.calculate_reward());

    println!("\n✅ NO OTHER CRYPTOCURRENCY REWARDS TOR RELAY WORK!");
}

fn demo_validator_selection() {
    println!("🎲 VALIDATOR SELECTION");
    println!("=====================");

    let mut registry = ValidatorRegistry::new();

    // Create diverse validators
    let validators_data = vec![
        ("whale.onion", 10000, 0.3),  // High stake, low work
        ("worker.onion", 100, 0.8),   // Low stake, high work
        ("balanced.onion", 1000, 0.6), // Balanced
    ];

    let mut validators = Vec::new();
    for (i, (addr, stake, score)) in validators_data.iter().enumerate() {
        let pubkey = [(i + 1) as u8; 32];
        let validator = Validator::new(pubkey, *stake, addr.to_string(), 0).unwrap();
        registry.register(validator.clone()).unwrap();
        validators.push((validator, *score));
    }

    println!("Validators:");
    for (validator, score) in &validators {
        println!("  - {}: {} ONC (score: {:.2})",
            validator.onion_address,
            validator.stake,
            score);
    }

    // Create contribution proofs
    let candidates: Vec<_> = validators
        .iter()
        .map(|(v, score)| {
            let poc = create_mock_poc(v.pubkey, *score);
            (v, poc)
        })
        .collect();

    let selector = ValidatorSelector::default();

    println!("\nSelection Simulation (1000 rounds):");
    let mut selection_counts = std::collections::HashMap::new();

    for height in 0..1000 {
        let prev_hash = [height as u8; 32];
        if let Some(selected) = selector.select_validator(&candidates, &prev_hash, height) {
            *selection_counts.entry(selected).or_insert(0) += 1;
        }
    }

    for (validator, _) in &validators {
        let count = selection_counts.get(&validator.pubkey).unwrap_or(&0);
        let percentage = (*count as f64 / 1000.0) * 100.0;
        println!("  - {}: selected {} times ({:.1}%)",
            validator.onion_address,
            count,
            percentage);
    }

    println!("\n✅ High-work validators get selected more often!");
}

fn demo_genesis_mining() {
    println!("🌱 GENESIS MINING (Fair Launch)");
    println!("================================");

    let config = GenesisConfig::default();
    let mut genesis = GenesisMining::new(config.clone(), 0);

    println!("Genesis Phase:");
    println!("  - Duration: 6 months");
    println!("  - Total Supply: 1,000,000 ONC");
    println!("  - Distribution: 100% to Tor relay operators");
    println!("  - NO pre-mine, NO ICO, completely FAIR\n");

    // Simulate 3 relay operators
    let operators = vec![
        ("Early adopter (day 1)", [1u8; 32], "early.onion", 0, 100 * 1024 * 1024 * 1024u64),
        ("Mid participant (month 2)", [2u8; 32], "mid.onion", 60 * 24 * 3600, 80 * 1024 * 1024 * 1024),
        ("Late joiner (month 4)", [3u8; 32], "late.onion", 120 * 24 * 3600, 50 * 1024 * 1024 * 1024),
    ];

    for (name, pubkey, addr, reg_time, bytes) in &operators {
        genesis.register_relay(*pubkey, addr.to_string(), *reg_time);
        genesis.record_relay_activity(pubkey, *bytes, 86400 * 30); // 30 days uptime

        let rewards = genesis.calculate_rewards(pubkey, config.duration_seconds);
        println!("{}", name);
        println!("  - Relayed: {} GB", bytes / (1024 * 1024 * 1024));
        println!("  - Rewards: {} ONC", rewards);
    }

    let stats = genesis.stats();
    println!("\nGenesis Stats:");
    println!("  - Total relay nodes: {}", stats.total_relay_nodes);
    println!("  - Total relayed: {} GB", stats.total_bytes_relayed / (1024 * 1024 * 1024));

    println!("\n✅ Early participants get bonus, but everyone can join!");
}

// Helper function
fn create_mock_poc(pubkey: [u8; 32], total_score: f64) -> ProofOfContribution {
    let score = ContributionScore {
        stake_score: total_score * 0.4,
        relay_score: total_score * 0.3,
        bandwidth_score: total_score * 0.15,
        uptime_score: total_score * 0.1,
        storage_score: total_score * 0.05,
        weights: ScoreWeights::default(),
    };

    ProofOfContribution {
        validator_pubkey: pubkey,
        score,
        timestamp: 0,
    }
}
