//! GHOSTDAG consensus implementation for Synor blockchain.
//!
//! This crate implements the GHOSTDAG (Greedy Heaviest-Observed Sub-Tree Directed Acyclic Graph)
//! protocol, based on Kaspa's design with modifications for Synor.
//!
//! # GHOSTDAG Overview
//!
//! GHOSTDAG allows multiple blocks to be created in parallel while maintaining
//! a consistent ordering through a "blue set" selection algorithm.
//!
//! Key concepts:
//! - **DAG**: Directed Acyclic Graph where blocks can have multiple parents
//! - **Blue Set**: The "honest" chain of blocks, selected using k-cluster
//! - **Blue Score**: Cumulative count of blue blocks in ancestry
//! - **k parameter**: Controls how many parallel blocks are allowed (antichain width)
//!
//! # Performance Targets
//!
//! - Block time: ~100ms (10 blocks/second)
//! - Max parents per block: 64
//! - k parameter: 18 (allows ~18 parallel miners)

#![allow(dead_code)]

pub mod dag;
pub mod dagknight;
pub mod ghostdag;
pub mod latency;
pub mod ordering;
pub mod pruning;
pub mod reachability;

pub use dag::{BlockDag, BlockRelations, DagError};
pub use dagknight::{
    calculate_optimal_k, calculate_optimal_k_for_config, estimate_throughput,
    AdaptiveKBounds, ConfirmationConfidence, ConfirmationStatus, DagKnightManager,
};
pub use ghostdag::{GhostdagData, GhostdagError, GhostdagManager};
pub use latency::{LatencySample, LatencyStats, LatencyTracker};
pub use ordering::{BlockOrdering, OrderedBlock};
pub use pruning::{PruningConfig, PruningManager};
pub use reachability::{ReachabilityError, ReachabilityStore};

use synor_types::Hash256;

/// Block ID type (hash of block header).
pub type BlockId = Hash256;

/// Blue score - cumulative count of blue ancestors.
pub type BlueScore = u64;

/// DAA score - difficulty adjustment algorithm score.
pub type DaaScore = u64;

/// GHOSTDAG k parameter - controls antichain width.
/// Higher k = more parallel blocks allowed = higher throughput
/// but also more complex blue set calculation.
pub const GHOSTDAG_K: u8 = 18;

/// Maximum number of parents a block can have.
pub const MAX_BLOCK_PARENTS: usize = 64;

/// Merge depth - how many blocks back we consider for merging.
pub const MERGE_DEPTH: u64 = 3600; // ~6 minutes at 10 bps

/// Finality depth - after this many confirmations, blocks are final.
pub const FINALITY_DEPTH: u64 = 86400; // ~2.4 hours at 10 bps

/// Pruning depth - how many blocks to keep in memory.
pub const PRUNING_DEPTH: u64 = 288_000; // ~8 hours at 10 bps

// ============================================================================
// DAGKnight Block Rate Configurations
// ============================================================================

/// Block rate configuration for different throughput modes.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BlockRateConfig {
    /// Standard 10 BPS (100ms block time) - default GHOSTDAG
    Standard,
    /// Enhanced 32 BPS (~31ms block time) - Phase 13 upgrade
    Enhanced,
    /// Maximum 100 BPS (10ms block time) - stretch goal
    Maximum,
}

impl BlockRateConfig {
    /// Returns the blocks per second for this configuration.
    pub const fn bps(&self) -> f64 {
        match self {
            BlockRateConfig::Standard => 10.0,
            BlockRateConfig::Enhanced => 32.0,
            BlockRateConfig::Maximum => 100.0,
        }
    }

    /// Returns the target block time in milliseconds.
    pub const fn block_time_ms(&self) -> u64 {
        match self {
            BlockRateConfig::Standard => 100,
            BlockRateConfig::Enhanced => 31,
            BlockRateConfig::Maximum => 10,
        }
    }

    /// Returns the recommended k parameter for this block rate.
    /// Higher block rates need higher k to accommodate network latency.
    pub const fn recommended_k(&self) -> u8 {
        match self {
            BlockRateConfig::Standard => 18,
            BlockRateConfig::Enhanced => 32,
            BlockRateConfig::Maximum => 64,
        }
    }

    /// Returns the merge depth adjusted for block rate.
    pub const fn merge_depth(&self) -> u64 {
        match self {
            BlockRateConfig::Standard => 3600,      // ~6 min at 10 bps
            BlockRateConfig::Enhanced => 11520,     // ~6 min at 32 bps
            BlockRateConfig::Maximum => 36000,      // ~6 min at 100 bps
        }
    }

    /// Returns the finality depth adjusted for block rate.
    pub const fn finality_depth(&self) -> u64 {
        match self {
            BlockRateConfig::Standard => 86400,     // ~2.4 hours at 10 bps
            BlockRateConfig::Enhanced => 276480,    // ~2.4 hours at 32 bps
            BlockRateConfig::Maximum => 864000,     // ~2.4 hours at 100 bps
        }
    }

    /// Returns the pruning depth adjusted for block rate.
    pub const fn pruning_depth(&self) -> u64 {
        match self {
            BlockRateConfig::Standard => 288_000,   // ~8 hours at 10 bps
            BlockRateConfig::Enhanced => 921_600,   // ~8 hours at 32 bps
            BlockRateConfig::Maximum => 2_880_000,  // ~8 hours at 100 bps
        }
    }
}

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

    #[test]
    #[allow(clippy::assertions_on_constants)]
    fn test_constants() {
        assert!(GHOSTDAG_K > 0);
        assert!(MAX_BLOCK_PARENTS >= GHOSTDAG_K as usize);
        assert!(FINALITY_DEPTH > MERGE_DEPTH);
    }
}
