//! Model storage and metadata configuration structures.
//!
//! This module defines configuration structures for managing ML model metadata,
//! training metrics, and architectural information. Used for model versioning,
//! performance tracking, and deployment management in the Foxhunt trading system.

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use uuid::Uuid;

/// Comprehensive metadata for ML model storage and tracking.
///
/// Contains all information necessary for model identification, versioning,
/// and performance tracking. Used for model lifecycle management and
/// deployment coordination across the trading system.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelRegistryEntry {
    /// Unique identifier for this model instance
    pub id: Uuid,
    /// Human-readable model name (e.g., "mamba2-price-prediction")
    pub name: String,
    /// Semantic version string (e.g., "1.2.3")
    pub version: String,
    /// Timestamp when this model was created/trained
    pub created_at: DateTime<Utc>,
    /// Timestamp when this model metadata was last updated
    pub updated_at: DateTime<Utc>,
    /// Training performance metrics for model evaluation
    pub training_metrics: TrainingMetrics,
    /// Model architecture and hyperparameter configuration
    pub architecture: ModelArchitecture,
}

/// Training performance metrics for model evaluation.
///
/// Captures key performance indicators from model training to enable
/// comparison between different model versions and architectures.
///
/// Essential for model selection and performance monitoring.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrainingMetrics {
    /// Final training accuracy (0.0 to 1.0)
    pub accuracy: f64,
    /// Final training loss value
    pub loss: f64,
    /// Final validation accuracy (0.0 to 1.0)
    pub validation_accuracy: f64,
    /// Final validation loss value
    pub validation_loss: f64,
    /// Number of training epochs completed
    pub epochs: u32,
    /// Total training time in seconds
    pub training_time_seconds: f64,
}

/// Model architecture and hyperparameter specification.
///
/// Defines the structural configuration of ML models including layer
/// dimensions, activation functions, and optimization parameters.
///
/// Used for model reconstruction and hyperparameter tracking.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelArchitecture {
    /// Model type identifier (e.g., "mamba2", "transformer", "dqn")
    pub model_type: String,
    /// Input feature dimension size
    pub input_dim: usize,
    /// Output prediction dimension size
    pub output_dim: usize,
    /// Hidden layer sizes in order from input to output
    pub hidden_layers: Vec<usize>,
    /// Activation function name (e.g., "relu", "gelu", "swish")
    pub activation: String,
    /// Optimizer type (e.g., "adam", "sgd", "adamw")
    pub optimizer: String,
    /// Learning rate used during training
    pub learning_rate: f64,
}

/// Storage configuration for model artifacts
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageConfig {
    /// Storage type (e.g., "local", "s3")
    pub storage_type: String,
    /// Local base path for file storage (required for "local" storage type)
    pub local_base_path: Option<PathBuf>,
    /// Enable compression for stored models
    pub enable_compression: bool,
}

impl Default for StorageConfig {
    fn default() -> Self {
        Self {
            storage_type: "local".to_owned(),
            local_base_path: Some(PathBuf::from("/tmp/foxhunt/models")),
            enable_compression: false,
        }
    }
}

impl StorageConfig {
    /// Create StorageConfig from environment variables
    ///
    /// # Errors
    /// Returns error if the operation fails
    pub fn from_env() -> Result<Self, Box<dyn std::error::Error>> {
        let storage_type = std::env::var("STORAGE_TYPE").unwrap_or_else(|_| "local".to_owned());
        let local_base_path = std::env::var("STORAGE_LOCAL_PATH")
            .ok()
            .map(PathBuf::from)
            .or_else(|| Some(PathBuf::from("/tmp/foxhunt/models")));
        let enable_compression = std::env::var("STORAGE_ENABLE_COMPRESSION")
            .ok()
            .and_then(|v| v.parse().ok())
            .unwrap_or(false);

        Ok(Self {
            storage_type,
            local_base_path,
            enable_compression,
        })
    }
}
