//! Meta-labeling framework for separating direction prediction from confidence/bet sizing
//!
//! Meta-labeling is a powerful technique that separates the prediction of direction
//! from the decision of whether to place a bet. This allows for more sophisticated
//! trading strategies with better risk management.

use std::time::Instant;

use serde::{Deserialize, Serialize};

use super::gpu_acceleration::LabelingError;
use super::types::{EventLabel, MetaLabel};

/// Meta-labeling engine for advanced trading strategies
#[derive(Debug)]
pub struct MetaLabelingEngine {
    config: MetaLabelConfig,
}

/// Configuration for meta-labeling
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetaLabelConfig {
    pub confidence_threshold: f64,
    pub min_bet_size: f64,
    pub max_bet_size: f64,
}

impl MetaLabelConfig {
    pub const fn standard() -> Self {
        Self {
            confidence_threshold: 0.5,
            min_bet_size: 0.01,
            max_bet_size: 0.10,
        }
    }
}

impl MetaLabelingEngine {
    pub const fn new(config: MetaLabelConfig) -> Self {
        Self { config }
    }

    pub fn apply_meta_labeling(
        &self,
        _prediction: i32,
        label: &EventLabel,
    ) -> Result<MetaLabel, LabelingError> {
        let _start_time = Instant::now();

        // Production implementation
        let confidence = 0.8;
        let bet_size = 0.05;
        let meta_prediction = if confidence > self.config.confidence_threshold {
            1
        } else {
            0
        };
        let expected_return = label.return_as_ratio() * confidence;

        Ok(MetaLabel {
            timestamp_ns: label.event_timestamp_ns,
            confidence,
            prediction: meta_prediction,
            bet_size,
            expected_return,
        })
    }
}

#[cfg(test)]
#[allow(clippy::inconsistent_digit_grouping)]
mod tests {
    use super::*;
    use crate::types::BarrierResult;

    #[test]
    fn test_meta_labeling_engine() -> Result<(), LabelingError> {
        let config = MetaLabelConfig::standard();
        let engine = MetaLabelingEngine::new(config);

        // Create a high-quality profitable label
        let barrier_result = BarrierResult::ProfitTarget;

        let label = EventLabel::new(
            1692000000_000_000_000 - 3600_000_000_000,
            10000,
            barrier_result,
            1,
            500, // 5% return
            0.9, // high quality
            50,
        );

        let result = engine.apply_meta_labeling(1, &label)?;

        assert_eq!(result.prediction, 1); // Should bet
        assert!(result.confidence > 0.6);
        assert!(result.bet_size > 0.0);
        assert!(result.expected_return > 0.0);

        Ok(())
    }
}
