use pyo3::exceptions::PyRuntimeError;
use pyo3::PyErr;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum HorizonError {
    #[error("risk violation: {0}")]
    Risk(#[from] RiskViolation),

    #[error("exchange error: {0}")]
    Exchange(String),

    #[error("order error: {0}")]
    Order(String),

    #[error("market not found: {0}")]
    MarketNotFound(String),

    #[error("internal error: {0}")]
    Internal(String),

    #[error("auth error: {0}")]
    Auth(String),
}

impl From<HorizonError> for PyErr {
    fn from(err: HorizonError) -> PyErr {
        match &err {
            HorizonError::Auth(_) => {
                pyo3::exceptions::PyPermissionError::new_err(err.to_string())
            }
            HorizonError::MarketNotFound(_) => {
                pyo3::exceptions::PyKeyError::new_err(err.to_string())
            }
            HorizonError::Risk(_) => {
                pyo3::exceptions::PyValueError::new_err(err.to_string())
            }
            _ => PyRuntimeError::new_err(err.to_string()),
        }
    }
}

#[derive(Debug, Clone, Error)]
pub enum RiskViolation {
    #[error("kill switch active: {reason}")]
    KillSwitchActive { reason: String },

    #[error("position limit exceeded: market {market_id} projected {projected:.1} (max {limit:.1})")]
    PositionLimitExceeded {
        market_id: String,
        projected: f64,
        limit: f64,
    },

    #[error("portfolio notional exceeded: projected {projected:.2} (max {limit:.2})")]
    PortfolioNotionalExceeded { projected: f64, limit: f64 },

    #[error("daily drawdown exceeded: {current_pct:.1}% (max {limit_pct:.1}%)")]
    DailyDrawdownExceeded { current_pct: f64, limit_pct: f64 },

    #[error("rate limit exceeded")]
    RateLimitExceeded,

    #[error("invalid price: {price} (must be {min}-{max})")]
    InvalidPrice { price: f64, min: f64, max: f64 },

    #[error("invalid size: {size} (must be > 0 and <= {max})")]
    InvalidSize { size: f64, max: f64 },

    #[error("duplicate order detected within dedup window")]
    DuplicateOrder,

    #[error("event position limit exceeded: projected {projected:.1} (max {limit:.1})")]
    EventPositionLimitExceeded { projected: f64, limit: f64 },
}
