//! Liquid Neural Networks for Ultra-Low Latency HFT
//!
//! Implementation of Liquid Time-constant (LTC) and Closed-form Continuous-time (`CfC`)
//! neural networks with fixed-point arithmetic for sub-100μs inference.

use std::error::Error;
use std::fmt;

use serde::{Deserialize, Serialize};

// Import MarketRegime from core types to avoid type conflicts
use ml_core::MLError;
use common::trading::MarketRegime;

pub mod activation;
pub mod candle_cfc;
pub mod cells;
pub mod network;
pub mod ode_solvers;
pub mod training;

#[cfg(test)]
mod tests;

// Re-export main types for external usage
pub use activation::ActivationType;
pub use candle_cfc::{BackboneMLP, CandleCfCNetwork, CfCCell, CfCTrainConfig, DeviceConfig};
pub use cells::{CfCConfig, LTCConfig};
pub use network::{LayerConfig, LiquidNetwork, LiquidNetworkConfig, OutputLayerConfig};
pub use ode_solvers::SolverType;
pub use training::{
    CandleCfCTrainer, CfCTrainerConfig, LiquidTrainer, LiquidTrainingConfig, TrainingBatch,
    TrainingMetrics, TrainingSample, TrainingUtils,
};

/// Fixed-point arithmetic for ultra-low latency inference
pub const PRECISION: i64 = 100_000_000; // 8 decimal places

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default)]
pub struct FixedPoint(pub i64);

impl FixedPoint {
    pub fn from_f64(value: f64) -> Self {
        FixedPoint((value * PRECISION as f64) as i64)
    }

    pub fn to_f64(self) -> f64 {
        self.0 as f64 / PRECISION as f64
    }

    pub const fn zero() -> Self {
        FixedPoint(0)
    }

    pub const fn one() -> Self {
        FixedPoint(PRECISION)
    }

    pub const fn is_finite(&self) -> bool {
        self.0.abs() < i64::MAX / 2
    }
}

impl std::ops::Add for FixedPoint {
    type Output = Result<FixedPoint>;

    fn add(self, rhs: FixedPoint) -> Self::Output {
        self.0
            .checked_add(rhs.0)
            .map(FixedPoint)
            .ok_or(LiquidError::Overflow("Addition overflow".to_owned()))
    }
}

impl std::ops::Sub for FixedPoint {
    type Output = Result<FixedPoint>;

    fn sub(self, rhs: FixedPoint) -> Self::Output {
        self.0
            .checked_sub(rhs.0)
            .map(FixedPoint)
            .ok_or(LiquidError::Overflow("Subtraction overflow".to_owned()))
    }
}

impl std::ops::Mul for FixedPoint {
    type Output = Result<FixedPoint>;

    fn mul(self, rhs: FixedPoint) -> Self::Output {
        let result = ((self.0 as i128) * (rhs.0 as i128)) / (PRECISION as i128);
        if result > i64::MAX as i128 || result < i64::MIN as i128 {
            Err(LiquidError::Overflow("Multiplication overflow".to_owned()))
        } else {
            Ok(FixedPoint(result as i64))
        }
    }
}

impl std::ops::Div for FixedPoint {
    type Output = Result<FixedPoint>;

    fn div(self, rhs: FixedPoint) -> Self::Output {
        if rhs.0 == 0 {
            return Err(LiquidError::DivisionByZero);
        }
        let result = ((self.0 as i128) * (PRECISION as i128)) / (rhs.0 as i128);
        if result > i64::MAX as i128 || result < i64::MIN as i128 {
            Err(LiquidError::Overflow("Division overflow".to_owned()))
        } else {
            Ok(FixedPoint(result as i64))
        }
    }
}

/// Liquid Neural Network specific errors
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LiquidError {
    InvalidConfiguration(String),
    InvalidInput(String),
    Overflow(String),
    DivisionByZero,
    InferenceError(String),
    TrainingError(String),
    SolverError(String),
}

impl fmt::Display for LiquidError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LiquidError::InvalidConfiguration(msg) => write!(f, "Invalid configuration: {}", msg),
            LiquidError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
            LiquidError::Overflow(msg) => write!(f, "Overflow error: {}", msg),
            LiquidError::DivisionByZero => write!(f, "Division by zero"),
            LiquidError::InferenceError(msg) => write!(f, "Inference error: {}", msg),
            LiquidError::TrainingError(msg) => write!(f, "Training error: {}", msg),
            LiquidError::SolverError(msg) => write!(f, "ODE solver error: {}", msg),
        }
    }
}

impl Error for LiquidError {}

impl From<LiquidError> for MLError {
    fn from(err: LiquidError) -> Self {
        match err {
            LiquidError::InvalidConfiguration(msg) => MLError::ConfigError(msg),
            LiquidError::InvalidInput(msg) => MLError::InvalidInput(msg),
            LiquidError::InferenceError(msg) => MLError::InferenceError(msg),
            LiquidError::TrainingError(msg) => MLError::TrainingError(msg),
            LiquidError::Overflow(_)
            | LiquidError::DivisionByZero
            | LiquidError::SolverError(_) => MLError::ModelError(err.to_string()),
        }
    }
}

impl From<MLError> for LiquidError {
    fn from(err: MLError) -> Self {
        match err {
            MLError::ConfigError(msg) => {
                LiquidError::InvalidConfiguration(msg)
            },
            MLError::InvalidInput(msg) => LiquidError::InvalidInput(msg),
            MLError::InferenceError(msg) => LiquidError::InferenceError(msg),
            MLError::TrainingError(msg) => LiquidError::TrainingError(msg),
            MLError::DimensionMismatch { .. }
            | MLError::GraphError { .. }
            | MLError::ResourceLimit { .. }
            | MLError::SerializationError { .. }
            | MLError::ValidationError { .. }
            | MLError::ConcurrencyError { .. }
            | MLError::InitializationError { .. }
            | MLError::ModelError(_)
            | MLError::NotTrained(_)
            | MLError::AnyhowError(_)
            | MLError::TensorCreationError { .. }
            | MLError::TensorOperationError(_)
            | MLError::LockError(_)
            | MLError::ModelNotFound(_)
            | MLError::InsufficientData(_)
            | MLError::CheckpointError(_)
            | MLError::DeviceError(_) => LiquidError::InferenceError(err.to_string()),
        }
    }
}

pub type Result<T> = std::result::Result<T, LiquidError>;

/// Network type for liquid neural networks
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum NetworkType {
    LTC,   // Liquid Time-constant
    CfC,   // Closed-form Continuous-time
    Mixed, // Combination of LTC and CfC layers
}

// REMOVED: MarketRegime enum - now using common::MarketRegime instead
// This eliminates the type conflict and ensures consistency across the entire system

/// Performance metrics for liquid networks
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceMetrics {
    pub total_inferences: u64,
    pub average_inference_time_ns: u64,
    pub average_inference_time_us: f64,
    pub total_parameters: usize,
    pub current_regime: MarketRegime, // Now uses core MarketRegime enum
    pub regime_switches: u32,
    pub last_adaptation_time: Option<u64>, // Store as timestamp millis instead of Instant
}
