//! # Unified Asset Type - CANONICAL SINGLE SOURCE OF TRUTH
//!
//! This module provides the definitive UnifiedAsset type for the entire Foxhunt system.
//! ALL services MUST use this canonical definition to avoid compilation conflicts.

use std::collections::HashMap;
use std::fmt;

use chrono::{DateTime, Utc};
// CANONICAL TYPE IMPORTS - Import directly from common types
use serde::{Deserialize, Serialize};
use common::{Currency, Price, Quantity, Symbol};
use rust_decimal::Decimal;

// ============================================================================
// ASSET TYPE DEFINITIONS - CANONICAL SINGLE SOURCE OF TRUTH
// ============================================================================

/// Asset classification for trading strategies and risk management
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// AssetClass
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub enum AssetClass {
    /// Equity securities (stocks, ETFs)
    Equity,
    /// Fixed income securities
    FixedIncome,
    /// Foreign exchange pairs
    Fx,
    /// Commodities
    Commodities,
    /// Cryptocurrency
    Crypto,
    /// Derivatives
    Derivatives,
}

impl fmt::Display for AssetClass {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Equity => write!(f, "Equity"),
            Self::FixedIncome => write!(f, "FixedIncome"),
            Self::Fx => write!(f, "Fx"),
            Self::Commodities => write!(f, "Commodities"),
            Self::Crypto => write!(f, "Crypto"),
            Self::Derivatives => write!(f, "Derivatives"),
        }
    }
}

impl AssetClass {
    /// Get all asset class variants
    #[must_use]
    pub fn all() -> Vec<Self> {
        vec![
            Self::Equity,
            Self::FixedIncome,
            Self::Fx,
            Self::Commodities,
            Self::Crypto,
            Self::Derivatives,
        ]
    }
}

/// `Option` types
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// OptionType
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub enum OptionType {
    // Call variant
    Call,
    // Put variant
    Put,
}

/// Swap types
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// SwapType
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub enum SwapType {
    // InterestRate variant
    InterestRate,
    // Currency variant
    Currency,
    // Commodity variant
    Commodity,
}

/// Specific asset type with detailed classification
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
/// AssetType
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub enum AssetType {
    /// Generic stock
    Stock,
    /// Common stock with exchange and sector
    CommonStock { exchange: String, sector: String },
    /// Exchange-traded fund
    ETF {
        exchange: String,
        expense_ratio: Option<Decimal>,
    },
    /// Major currency pair
    MajorPair { base: Currency, quote: Currency },
    /// Spot cryptocurrency
    SpotCrypto {
        base: String,
        quote: String,
        exchange: String,
    },
    /// `Option` contract
    Option {
        underlying: Symbol,
        option_type: OptionType,
        strike: Price,
        expiry: DateTime<Utc>,
    },
    /// Future contract
    Future {
        underlying: Symbol,
        expiry: DateTime<Utc>,
        contract_size: Quantity,
    },
    /// Swap contract
    Swap {
        swap_type: SwapType,
        notional: Price,
        maturity: DateTime<Utc>,
    },
}

/// Settlement type for different asset classes
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// SettlementType
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub enum SettlementType {
    /// Regular way settlement with T+ days
    RegularWay(u32),
    /// Cash settlement same day
    Cash,
    /// Delivery vs Payment
    DvP,
    /// Custom settlement period
    Custom(u32),
}

/// Price quote structure
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
/// PriceQuote
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub struct PriceQuote {
    /// Bid
    pub bid: Option<Price>,
    /// Ask
    pub ask: Option<Price>,
    /// Timestamp
    pub timestamp: DateTime<Utc>,
    /// Venue
    pub venue: String,
}

/// The canonical unified asset type used across all Foxhunt services
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
/// UnifiedAsset
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub struct UnifiedAsset {
    /// Primary identifier
    pub symbol: Symbol,
    /// Asset classification
    pub asset_class: AssetClass,
    /// Detailed asset type
    pub asset_type: AssetType,
    /// Trading currency
    pub currency: Currency,
    /// Minimum quantity increment
    pub lot_size: Quantity,
    /// Price precision (decimal places)
    pub tick_size: Price,
    /// Current market data
    pub quote: Option<PriceQuote>,
    /// Settlement information
    pub settlement: SettlementType,
    /// Trading venue
    pub venue: String,
    /// Whether asset is tradeable
    pub is_tradeable: bool,
    /// Additional metadata
    pub metadata: HashMap<String, String>,
}

impl UnifiedAsset {
    /// Create a new unified asset
    #[must_use]
    pub fn new(
        symbol: Symbol,
        asset_class: AssetClass,
        asset_type: AssetType,
        currency: Currency,
    ) -> Self {
        Self {
            symbol,
            asset_class,
            asset_type,
            currency,
            lot_size: Quantity::from_f64(1.0).unwrap_or(Quantity::ZERO),
            tick_size: Price::from_str("0.01").unwrap_or_else(|_| {
                Price::from_f64(0.01).unwrap_or_else(|_| {
                    tracing::warn!("Failed to create default tick size, using Price::ONE");
                    Price::ONE
                })
            }),
            quote: None,
            settlement: SettlementType::RegularWay(2),
            venue: String::new(),
            is_tradeable: true,
            metadata: HashMap::new(),
        }
    }

    /// Check if asset can be traded
    #[must_use]
    pub const fn is_tradeable(&self) -> bool {
        self.is_tradeable
    }

    /// Get asset class
    #[must_use]
    pub const fn asset_class(&self) -> AssetClass {
        self.asset_class
    }
}

/// Unified asset registry for managing all asset types
#[derive(Debug, Clone, Default)]
/// AssetRegistry
/// 
/// Auto-generated documentation placeholder - enhance with specifics
pub struct AssetRegistry {
    assets: HashMap<Symbol, UnifiedAsset>,
}

impl AssetRegistry {
    /// Create new asset registry
    #[must_use]
    pub fn new() -> Self {
        Self {
            assets: HashMap::new(),
        }
    }

    /// Add an asset to the registry
    pub fn add_asset(&mut self, symbol: Symbol, asset: UnifiedAsset) {
        self.assets.insert(symbol, asset);
    }

    /// Get an asset by symbol
    #[must_use]
    pub fn get_asset(&self, symbol: &Symbol) -> Option<&UnifiedAsset> {
        self.assets.get(symbol)
    }

    /// Get total number of assets
    #[must_use]
    pub fn total_assets(&self) -> usize {
        self.assets.len()
    }

    /// Count assets by class
    #[must_use]
    pub fn assets_by_class_count(&self, class: AssetClass) -> usize {
        self.assets
            .values()
            .filter(|asset| asset.asset_class() == class)
            .count()
    }
}
