use betex::prelude::*;

mod common;
use common::two_runner_market_config;

struct NoopHandler;

impl disrupt_rs::EventHandler<betex::engine::core::EngineEvent> for NoopHandler {
    fn on_event(
        &mut self,
        _event: &betex::engine::core::EngineEvent,
        _sequence: disrupt_rs::Sequence,
        _end_of_batch: bool,
    ) {
    }
}

fn temp_lmdb_path(test_name: &str) -> std::path::PathBuf {
    common::unique_path_under_target("replay", test_name)
}

#[test]
fn replay_determinism_smoke() {
    let cfg = Config {
        ring_size_pow2: 64,
        ..Default::default()
    };
    let wal_path = temp_lmdb_path("engine-replay-determinism");
    let _ = std::fs::remove_dir_all(&wal_path);

    let builder = EngineBuilder::with_markets(
        cfg.clone(),
        [two_runner_market_config(MarketId(1))],
        &wal_path,
    );
    let engine = match builder {
        Ok(b) => b
            .register_handler(NoopHandler, HandlerRecovery::LiveOnly, None)
            .build()
            .expect("start"),
        Err(e) => {
            if common::is_lmdb_unsupported(&e) {
                eprintln!("skipping LMDB WAL test: {e}");
                return;
            }
            panic!("builder: {e}");
        }
    };

    let handle = engine.handle();
    handle
        .submit(Command {
            correlation_id: Some(CorrelationId(1.to_string())),
            metadata: None,
            market_id: MarketId(1),
            kind: CommandKind::PlaceOrder {
                runner_id: RunnerId(1),
                account_id: AccountId::from(1),
                client_order_id: Some(ClientOrderId(42)),
                side: Side::Yes,
                odds: OddsX10000(10_100),
                stake: Money(100),
                persistence: Persistence::Persist,
                time_in_force: TimeInForce::FillOrKill {
                    min_fill: Some(Quantity(0)),
                },
            },
        })
        .expect("engine submit should succeed");

    // Allow to engine thread to process and publish before shutdown.
    std::thread::sleep(std::time::Duration::from_millis(50));

    drop(engine);

    // Restart from WAL and verify engine starts without errors
    let builder2 =
        EngineBuilder::with_markets(cfg, [two_runner_market_config(MarketId(1))], &wal_path);
    let engine2 = match builder2 {
        Ok(b) => b
            .register_handler(NoopHandler, HandlerRecovery::LiveOnly, None)
            .build()
            .expect("start2"),
        Err(e) => {
            if common::is_lmdb_unsupported(&e) {
                eprintln!("skipping LMDB WAL test: {e}");
                return;
            }
            panic!("builder2: {e}");
        }
    };

    drop(engine2);
    let _ = std::fs::remove_dir_all(&wal_path);
}
