use serde::{Deserialize, Serialize};

/// Trading phase of a market.
#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Hash,
    Default,
    Serialize,
    Deserialize,
    rkyv::Archive,
    rkyv::Serialize,
    rkyv::Deserialize,
    strum::Display,
    strum::AsRefStr,
)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
pub enum MarketPhase {
    /// Pre-event trading.
    #[default]
    Pre,
    /// Live/in-play trading.
    Live,
}

/// Trading capability of a market.
///
/// - `PreEventOnly`: market starts in `Pre` and never transitions to `Live`.
/// - `InPlayCapable`: market may trade in either phase and supports `Pre -> Live`.
/// - `LiveOnly`: market starts in `Live` and never transitions from `Pre`.
#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Hash,
    Serialize,
    Deserialize,
    rkyv::Archive,
    rkyv::Serialize,
    rkyv::Deserialize,
    strum::Display,
    strum::AsRefStr,
)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
pub enum MarketKind {
    PreEventOnly,
    InPlayCapable,
    LiveOnly,
}

impl MarketKind {
    pub fn supports_initial_phase(self, phase: MarketPhase) -> bool {
        match self {
            Self::PreEventOnly => phase == MarketPhase::Pre,
            Self::InPlayCapable => true,
            Self::LiveOnly => phase == MarketPhase::Live,
        }
    }

    pub fn can_transition_to_phase(self, from: MarketPhase, to: MarketPhase) -> bool {
        if from == to {
            return true;
        }
        matches!(
            (self, from, to),
            (Self::InPlayCapable, MarketPhase::Pre, MarketPhase::Live)
        )
    }
}

/// Market pricing/matching model.
#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Hash,
    Default,
    Serialize,
    Deserialize,
    rkyv::Archive,
    rkyv::Serialize,
    rkyv::Deserialize,
)]
// Keep the default externally tagged representation here; this enum also appears in compact
// serde-based binary snapshots where internally tagged enums are not supported.
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum MarketModel {
    /// Odds-based runner markets (the existing Betfair-style model).
    #[default]
    ExchangeOdds,
    /// Canonical YES-only prediction market with uniform probability ticks.
    ///
    /// - `max_price_ticks`: denominator for probability prices (e.g. 10_000 for 0.01% ticks)
    /// - valid tradable ticks: `1..max_price_ticks-1`
    BinaryYes { max_price_ticks: u16 },
}
