/// Demonstration of OnionCoin's unique timing obfuscation features
///
/// This example shows how OnionCoin uses Tor latency as a privacy feature
/// to make transaction timing analysis impossible.

use chrono::Utc;
use onioncoin_timing::*;
use onioncoin_timing::delay::DelaySequence;
use std::time::Instant;

#[tokio::main]
async fn main() {
    println!("=== OnionCoin Timing Obfuscation Demo ===\n");

    // 1. Fuzzy Timestamps
    demo_fuzzy_timestamps();
    println!();

    // 2. Time Range Proofs
    demo_time_proofs();
    println!();

    // 3. Delay Strategies
    demo_delays().await;
    println!();

    // 4. Mixing Pool
    demo_mixing_pool();
    println!();

    // 5. Complete Transaction Flow
    demo_complete_flow().await;
}

fn demo_fuzzy_timestamps() {
    println!("📅 FUZZY TIMESTAMPS");
    println!("------------------");

    let real_time = Utc::now();
    println!("Real creation time: {}", real_time.format("%Y-%m-%d %H:%M:%S"));

    // Create fuzzy time range
    let range = TimeRange::new_fuzzy(real_time);

    println!("Timestamp range:    {} to {}",
        chrono::DateTime::from_timestamp(range.earliest, 0).unwrap().format("%Y-%m-%d %H:%M:%S"),
        chrono::DateTime::from_timestamp(range.latest, 0).unwrap().format("%Y-%m-%d %H:%M:%S"),
    );

    println!("Range duration:     {} hours", range.duration_seconds() / 3600);
    println!("\n✅ Observer cannot determine exact creation time!");
}

fn demo_time_proofs() {
    println!("🔐 ZERO-KNOWLEDGE TIME PROOFS");
    println!("-----------------------------");

    let real_time = Utc::now();
    let seed = [42u8; 32];
    let range = TimeRange::new_fuzzy(real_time);

    let proof = TimeRangeProof::generate(&seed, real_time, &range)
        .expect("Proof generation failed");

    println!("Generated ZK proof:");
    println!("  - Earliest hash: {:x?}...", &proof.earliest_hash[..4]);
    println!("  - Latest hash:   {:x?}...", &proof.latest_hash[..4]);
    println!("  - Time commit:   {:x?}...", &proof.time_commitment[..4]);

    let is_valid = proof.verify(&range);
    println!("\nProof verification: {}", if is_valid { "✅ VALID" } else { "❌ INVALID" });
    println!("Real time is hidden but provably within range!");
}

async fn demo_delays() {
    println!("⏱️  STRATEGIC DELAYS");
    println!("-------------------");

    // Wallet broadcast delay
    println!("1. Wallet broadcast delay (5-60 min):");
    let strategy = DelayStrategy::wallet_broadcast();
    let delay = strategy.calculate();
    println!("   Random delay: {} seconds ({:.1} minutes)", delay.as_secs(), delay.as_secs() as f64 / 60.0);

    // Dandelion STEM delays
    println!("\n2. Dandelion STEM sequence (1-4 hops):");
    let mut sequence = DelaySequence::dandelion_stem();
    println!("   Hops: {}", sequence.len());

    let mut hop = 1;
    while let Some(strategy) = sequence.next() {
        let delay = strategy.calculate();
        println!("   Hop {}: {} seconds", hop, delay.as_secs());
        hop += 1;
    }

    // Node rebroadcast delay
    println!("\n3. Node rebroadcast delay (10s-2min):");
    let strategy = DelayStrategy::node_rebroadcast();
    let delay = strategy.calculate();
    println!("   Random delay: {} seconds", delay.as_secs());

    println!("\n✅ Multiple layers of random delays obscure transaction origin!");
}

fn demo_mixing_pool() {
    println!("🔀 MIXING POOL");
    println!("-------------");

    let mut pool = MixingPool::<u32>::new(
        std::time::Duration::from_secs(10),  // 10s min (demo)
        std::time::Duration::from_secs(30),  // 30s max (demo)
        100,
    );

    println!("Adding transactions to mixing pool...");
    for i in 1..=10 {
        pool.add(i);
        println!("  Added tx #{}", i);
    }

    println!("\nPool size: {} transactions", pool.len());
    println!("Waiting for minimum batch duration...");

    std::thread::sleep(std::time::Duration::from_secs(11));

    if pool.should_release() {
        let batch = pool.release_batch();
        println!("\n✅ Released shuffled batch:");
        println!("  Original order: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10");
        println!("  Shuffled order: {:?}", batch);
        println!("\nTemporal ordering destroyed!");
    }
}

async fn demo_complete_flow() {
    println!("🌊 COMPLETE TRANSACTION FLOW");
    println!("============================");

    let real_time = Utc::now();
    println!("T+0:00  User creates transaction");
    println!("        Real time: {}", real_time.format("%H:%M:%S"));

    // Step 1: Fuzzy timestamp
    let seed = [42u8; 32];
    let timing = TimingMetadata::new(real_time, &seed)
        .expect("Failed to create timing metadata");

    println!("        Timestamp range: ±{} hours", timing.time_range.duration_seconds() / 3600 / 2);

    // Step 2: Wallet delay
    println!("\nT+0:00  Wallet applies random delay...");
    let wallet_delay = DelayStrategy::Random {
        min: std::time::Duration::from_secs(2),  // Shortened for demo
        max: std::time::Duration::from_secs(5),
    };
    let actual_delay = wallet_delay.calculate();
    println!("        Waiting {} seconds", actual_delay.as_secs());

    let start = Instant::now();
    tokio::time::sleep(actual_delay).await;

    println!("T+{:04}  Transaction broadcast to Tor", start.elapsed().as_secs());

    // Step 3: Dandelion STEM
    println!("\nT+{:04}  Entering STEM phase...", start.elapsed().as_secs());
    let mut sequence = DelaySequence::new(vec![
        DelayStrategy::Fixed(std::time::Duration::from_secs(1)),
        DelayStrategy::Fixed(std::time::Duration::from_secs(1)),
    ]);

    let mut hop = 1;
    while let Some(strategy) = sequence.next() {
        strategy.sleep().await;
        println!("T+{:04}  STEM hop {} complete", start.elapsed().as_secs(), hop);
        hop += 1;
    }

    // Step 4: Transition to FLUFF
    println!("\nT+{:04}  Transitioning to FLUFF phase", start.elapsed().as_secs());
    println!("        Broadcasting to network...");

    tokio::time::sleep(std::time::Duration::from_secs(1)).await;

    println!("\nT+{:04}  ✅ Transaction propagated!", start.elapsed().as_secs());
    println!("\n🎯 PRIVACY ACHIEVED:");
    println!("   - Real creation time: HIDDEN (±{} hours ambiguity)", timing.time_range.duration_seconds() / 3600 / 2);
    println!("   - Origin node: UNKNOWN (Dandelion++ + Tor)");
    println!("   - Propagation path: UNTRACEABLE (random delays)");
    println!("   - Transaction correlation: VERY DIFFICULT (mixing pool)");
}
