use betex::{
    book::{BookEvent, BookEventExternallyTagged, BookEventUntagged, BookMarketState},
    prelude::Side,
    types::{MarketPhase, Money, OddsX10000, OrderId, RunnerId},
};
use serde_json::json;

#[test]
fn book_event_externally_tagged_serialization_shape() {
    let event = BookEvent::MarketStateChanged {
        to: BookMarketState::Suspended,
        reason: "manual suspend".to_string(),
    };

    let tagged: BookEventExternallyTagged = event.clone().into_externally_tagged();
    let value = serde_json::to_value(&tagged).expect("serialize externally-tagged event");

    assert_eq!(
        value,
        json!({
            "MARKET_STATE_CHANGED": {
                "to": "SUSPENDED",
                "reason": "manual suspend"
            }
        })
    );

    let decoded_tagged: BookEventExternallyTagged =
        serde_json::from_value(value).expect("deserialize externally-tagged event");
    let decoded_event: BookEvent = decoded_tagged.into();
    assert_eq!(decoded_event, event);
}

#[test]
fn book_event_native_still_serializes_as_externally_tagged() {
    let event = BookEvent::MarketStateChanged {
        to: BookMarketState::Suspended,
        reason: "native".to_string(),
    };

    let value = serde_json::to_value(&event).expect("serialize native book event");
    assert_eq!(
        value,
        json!({
            "MARKET_STATE_CHANGED": {
                "to": "SUSPENDED",
                "reason": "native"
            }
        })
    );
}

#[test]
fn book_event_untagged_serialization_shape() {
    let event = BookEvent::MarketStateChanged {
        to: BookMarketState::Open,
        reason: "resume".to_string(),
    };

    let untagged: BookEventUntagged = event.clone().into_untagged();
    let value = serde_json::to_value(&untagged).expect("serialize untagged event");

    assert_eq!(
        value,
        json!({
            "to": "OPEN",
            "reason": "resume"
        })
    );
}

#[test]
fn trade_matched_serialization_uses_market_phase_field() {
    let event = BookEvent::TradeMatched {
        correlation_id: Some("corr-1".to_string().into()),
        order_id: OrderId(100),
        account_id: "acct-1".into(),
        role: betex::book::TradeRole::Maker,
        runner_id: RunnerId(7),
        runner_label: "Home".to_string(),
        side: Side::Yes,
        market_phase: MarketPhase::Live,
        price: OddsX10000(25_000),
        stake: Money(125_000),
        counter_party: OrderId(101),
        counter_party_account_id: "acct-2".into(),
        remaining_stake: Money(25_000),
        matched_delta: Money(100_000),
    };

    let value = serde_json::to_value(&event).expect("serialize trade event");
    assert_eq!(
        value,
        json!({
            "TRADE_MATCHED": {
                "correlation_id": "corr-1",
                "order_id": 100,
                "account_id": "acct-1",
                "role": "MAKER",
                "runner_id": 7,
                "runner_label": "Home",
                "side": "YES",
                "market_phase": "LIVE",
                "price": 25000,
                "stake": 125000,
                "counter_party": 101,
                "counter_party_account_id": "acct-2",
                "remaining_stake": 25000,
                "matched_delta": 100000
            }
        })
    );
}
