"""Test all code snippets from docs/backtesting.mdx."""

import sys
import os
import traceback
import tempfile

# Ensure the project is importable
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

import horizon as hz

results = []


def run_snippet(name, fn):
    """Run a snippet wrapped in try/except, record PASS/FAIL."""
    try:
        fn()
        results.append((name, True, None))
        print(f"PASS: {name}")
    except Exception as e:
        results.append((name, False, str(e)))
        print(f"FAIL: {name}")
        traceback.print_exc()
        print()


# ---------------------------------------------------------------------------
# Snippet 1: Quick Start (lines 22-44)
# ---------------------------------------------------------------------------
def snippet_quick_start():
    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    result = hz.backtest(
        name="simple-backtest",
        markets=["my-market"],
        data=[
            {"timestamp": 1000, "price": 0.50},
            {"timestamp": 1001, "price": 0.52},
            {"timestamp": 1002, "price": 0.48},
            {"timestamp": 1003, "price": 0.55},
            {"timestamp": 1004, "price": 0.60},
        ],
        pipeline=[model, quoter],
    )
    print(result.summary())

run_snippet("Quick Start", snippet_quick_start)


# ---------------------------------------------------------------------------
# Snippet 2: Data Format - List of Dicts (lines 109-120)
# ---------------------------------------------------------------------------
def snippet_data_list_of_dicts():
    def model(ctx):
        return ctx.feed.price * 1.01

    def quoter(ctx, fair):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [
        {"timestamp": 1700000000, "price": 0.55, "bid": 0.54, "ask": 0.56, "volume": 100},
        {"timestamp": 1700000001, "price": 0.56, "bid": 0.55, "ask": 0.57, "volume": 150},
        {"timestamp": 1700000002, "price": 0.54, "bid": 0.53, "ask": 0.55, "volume": 80},
    ]

    result = hz.backtest(
        markets=["my-market"],
        data=data,
        pipeline=[model, quoter],
    )
    assert result is not None

run_snippet("Data Format - List of Dicts", snippet_data_list_of_dicts)


# ---------------------------------------------------------------------------
# Snippet 3: Data Format - CSV File (lines 128-138)
# SKIP: requires external CSV file on disk, but we can create a temp one
# ---------------------------------------------------------------------------
def snippet_data_csv():
    def model(ctx):
        return ctx.feed.price * 1.01

    def quoter(ctx, fair):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    # Create a temporary CSV file
    with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
        f.write("timestamp,price,bid,ask,volume\n")
        f.write("1700000000,0.55,0.54,0.56,100\n")
        f.write("1700000001,0.56,0.55,0.57,150\n")
        csv_path = f.name

    try:
        result = hz.backtest(
            markets=["my-market"],
            data=csv_path,
            pipeline=[model, quoter],
        )
        assert result is not None
    finally:
        os.unlink(csv_path)

run_snippet("Data Format - CSV File", snippet_data_csv)


# ---------------------------------------------------------------------------
# Snippet 4: Data Format - Pandas DataFrame (lines 146-159)
# ---------------------------------------------------------------------------
def snippet_data_dataframe():
    try:
        import pandas as pd
    except ImportError:
        print("  (pandas not installed, skipping)")
        return

    def model(ctx):
        return ctx.feed.price * 1.01

    def quoter(ctx, fair):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    df = pd.DataFrame({
        "timestamp": [1700000000, 1700000001, 1700000002],
        "price": [0.55, 0.56, 0.54],
        "bid": [0.54, 0.55, 0.53],
        "ask": [0.56, 0.57, 0.55],
        "volume": [100, 150, 80],
    })

    result = hz.backtest(
        markets=["my-market"],
        data=df,
        pipeline=[model, quoter],
    )
    assert result is not None

run_snippet("Data Format - Pandas DataFrame", snippet_data_dataframe)


# ---------------------------------------------------------------------------
# Snippet 5: Multi-Feed Dict (lines 165-182)
# ---------------------------------------------------------------------------
def snippet_multi_feed_dict():
    def model(ctx):
        return ctx.feed.price * 1.01

    def quoter(ctx, fair):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = {
        "polymarket_book": [
            {"timestamp": 1700000000, "price": 0.55, "bid": 0.54, "ask": 0.56},
            {"timestamp": 1700000001, "price": 0.56, "bid": 0.55, "ask": 0.57},
        ],
        "binance": [
            {"timestamp": 1700000000, "price": 0.60},
            {"timestamp": 1700000001, "price": 0.62},
        ],
    }

    result = hz.backtest(
        markets=["btc-above-100k"],
        data=data,
        feeds={"btc-above-100k": "polymarket_book"},
        pipeline=[model, quoter],
    )
    assert result is not None

run_snippet("Multi-Feed Dict", snippet_multi_feed_dict)


# ---------------------------------------------------------------------------
# Snippet 6: L2 Orderbook Simulation - Book Data Format (lines 197-217)
# Uses synthetic tick_data + book_data
# ---------------------------------------------------------------------------
def snippet_l2_book_data():
    def my_strategy(ctx):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    tick_data = [
        {"timestamp": 1700000000, "price": 0.55},
        {"timestamp": 1700000001, "price": 0.56},
    ]

    book_data = {
        "election-winner": [
            {
                "timestamp": 1700000000,
                "bids": [(0.54, 100), (0.53, 200), (0.52, 500)],
                "asks": [(0.56, 100), (0.57, 200), (0.58, 500)],
            },
            {
                "timestamp": 1700000001,
                "bids": [(0.55, 150), (0.54, 250)],
                "asks": [(0.57, 150), (0.58, 250)],
            },
        ],
    }

    result = hz.backtest(
        markets=["election-winner"],
        data=tick_data,
        pipeline=[my_strategy],
        book_data=book_data,
    )
    assert result is not None

run_snippet("L2 Book Data Format", snippet_l2_book_data)


# ---------------------------------------------------------------------------
# Snippet 7: Fill Model - Deterministic (lines 234-239)
# ---------------------------------------------------------------------------
def snippet_fill_deterministic():
    def my_strategy(ctx):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + t * 0.001} for t in range(200)]
    book_data = {
        "market": [
            {
                "timestamp": t,
                "bids": [(0.49 + t * 0.001, 100)],
                "asks": [(0.51 + t * 0.001, 100)],
            }
            for t in range(200)
        ],
    }

    result = hz.backtest(
        data=data,
        pipeline=[my_strategy],
        book_data=book_data,
        fill_model="deterministic",
    )
    assert result is not None

run_snippet("Fill Model - Deterministic", snippet_fill_deterministic)


# ---------------------------------------------------------------------------
# Snippet 8: Fill Model - Probabilistic (lines 250-257)
# ---------------------------------------------------------------------------
def snippet_fill_probabilistic():
    def my_strategy(ctx):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + t * 0.001} for t in range(200)]
    book_data = {
        "market": [
            {
                "timestamp": t,
                "bids": [(0.49 + t * 0.001, 100)],
                "asks": [(0.51 + t * 0.001, 100)],
            }
            for t in range(200)
        ],
    }

    result = hz.backtest(
        data=data,
        pipeline=[my_strategy],
        book_data=book_data,
        fill_model="probabilistic",
        fill_model_params={"lambda": 1.0, "queue_frac": 0.5},
        rng_seed=42,
    )
    assert result is not None

run_snippet("Fill Model - Probabilistic", snippet_fill_probabilistic)


# ---------------------------------------------------------------------------
# Snippet 9: Fill Model - GLFT (lines 273-280)
# ---------------------------------------------------------------------------
def snippet_fill_glft():
    def my_strategy(ctx):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + t * 0.001} for t in range(200)]
    book_data = {
        "market": [
            {
                "timestamp": t,
                "bids": [(0.49 + t * 0.001, 100)],
                "asks": [(0.51 + t * 0.001, 100)],
            }
            for t in range(200)
        ],
    }

    result = hz.backtest(
        data=data,
        pipeline=[my_strategy],
        book_data=book_data,
        fill_model="glft",
        fill_model_params={"intensity": 1.0, "kappa": 1.5},
        rng_seed=42,
    )
    assert result is not None

run_snippet("Fill Model - GLFT", snippet_fill_glft)


# ---------------------------------------------------------------------------
# Snippet 10: Market Impact (lines 297-305)
# ---------------------------------------------------------------------------
def snippet_market_impact():
    def my_strategy(ctx):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + t * 0.001} for t in range(200)]
    book_data = {
        "market": [
            {
                "timestamp": t,
                "bids": [(0.49 + t * 0.001, 100)],
                "asks": [(0.51 + t * 0.001, 100)],
            }
            for t in range(200)
        ],
    }

    result = hz.backtest(
        data=data,
        pipeline=[my_strategy],
        book_data=book_data,
        impact_temporary_bps=5.0,
        impact_permanent_fraction=0.3,
    )
    assert result is not None

run_snippet("Market Impact", snippet_market_impact)


# ---------------------------------------------------------------------------
# Snippet 11: Latency Simulation (lines 320-326)
# ---------------------------------------------------------------------------
def snippet_latency():
    def my_strategy(ctx):
        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + t * 0.001} for t in range(200)]
    book_data = {
        "market": [
            {
                "timestamp": t,
                "bids": [(0.49 + t * 0.001, 100)],
                "asks": [(0.51 + t * 0.001, 100)],
            }
            for t in range(200)
        ],
    }

    result = hz.backtest(
        data=data,
        pipeline=[my_strategy],
        book_data=book_data,
        latency_ms=50.0,
    )
    assert result is not None

run_snippet("Latency Simulation", snippet_latency)


# ---------------------------------------------------------------------------
# Snippet 12: Calibration Curve (lines 339-356)
# ---------------------------------------------------------------------------
def snippet_calibration_curve():
    from horizon._horizon import calibration_curve

    result = calibration_curve(
        predictions=[0.3, 0.7, 0.9, 0.1, 0.6, 0.8],
        outcomes=[0.0, 1.0, 1.0, 0.0, 1.0, 0.0],
        n_bins=5,
    )

    print(f"  Brier Score: {result.brier_score:.4f}")
    print(f"  Log Loss:    {result.log_loss:.4f}")
    print(f"  ECE:         {result.ece:.4f}")

    for center, freq, count in result.bins:
        print(f"    Predicted ~{center:.1%}: Actual {freq:.1%} (n={count})")

run_snippet("Calibration Curve", snippet_calibration_curve)


# ---------------------------------------------------------------------------
# Snippet 13: Log Loss (lines 361-368)
# ---------------------------------------------------------------------------
def snippet_log_loss():
    from horizon._horizon import log_loss

    ll = log_loss(
        predictions=[0.7, 0.3, 0.9],
        outcomes=[1.0, 0.0, 1.0],
    )
    print(f"  Log Loss: {ll:.4f}")

run_snippet("Log Loss", snippet_log_loss)


# ---------------------------------------------------------------------------
# Snippet 14: Edge Decay (lines 375-388)
# ---------------------------------------------------------------------------
def snippet_edge_decay():
    from horizon._horizon import edge_decay

    result = edge_decay(
        entry_prices=[0.45, 0.55, 0.40, 0.60],
        outcomes=[1.0, 1.0, 0.0, 0.0],
        entry_ts=[1000.0, 2000.0, 3000.0, 4000.0],
        resolution_ts=[5000.0, 5000.0, 5000.0, 5000.0],
        n_buckets=10,
    )

    print(f"  Edge half-life: {result.half_life_hours:.1f} hours")
    for hours, avg_edge in result.decay_curve:
        print(f"    {hours:.0f}h before resolution: {avg_edge:.4f} avg edge")

run_snippet("Edge Decay", snippet_edge_decay)


# ---------------------------------------------------------------------------
# Snippet 15: Walk-Forward Optimization (lines 398-431)
# Uses synthetic data to avoid network
# ---------------------------------------------------------------------------
def snippet_walk_forward():
    from horizon.walkforward import walk_forward

    # Create synthetic tick data (enough for 5 splits)
    tick_data = [
        {"timestamp": 1700000000 + t, "price": 0.50 + (t % 20) * 0.005}
        for t in range(2000)
    ]

    def pipeline_factory(params):
        spread = params["spread"]
        size = params["size"]

        def quoter(ctx):
            fair = ctx.feed.price
            return hz.quotes(fair=fair, spread=spread, size=size)

        return [quoter]

    result = walk_forward(
        data=tick_data,
        pipeline_factory=pipeline_factory,
        param_grid={
            "spread": [0.02, 0.04],
            "size": [5, 10],
        },
        n_splits=3,
        train_ratio=0.7,
        expanding=True,
        objective="sharpe_ratio",
    )

    for i, (window, params) in enumerate(zip(result.windows, result.best_params_per_window)):
        test = result.test_results[i]
        print(f"  Window {i}: best params={params}, OOS Sharpe={test.metrics.sharpe_ratio:.3f}")

    m = result.aggregate_metrics
    print(f"  Aggregate OOS: Return={m.total_return_pct:.2f}%, Sharpe={m.sharpe_ratio:.3f}")

run_snippet("Walk-Forward Optimization", snippet_walk_forward)


# ---------------------------------------------------------------------------
# Snippet 16: BacktestResult - metrics (lines 473-494)
# ---------------------------------------------------------------------------
def snippet_result_metrics():
    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + (t % 10) * 0.005} for t in range(500)]

    result = hz.backtest(
        markets=["mkt"],
        data=data,
        pipeline=[model, quoter],
    )

    m = result.metrics

    print(f"  Total Return:     ${m.total_return:.2f}")
    print(f"  Total Return %:   {m.total_return_pct:.2f}%")
    print(f"  CAGR:             {m.cagr:.2%}")
    print(f"  Sharpe Ratio:     {m.sharpe_ratio:.3f}")
    print(f"  Sortino Ratio:    {m.sortino_ratio:.3f}")
    print(f"  Calmar Ratio:     {m.calmar_ratio:.3f}")
    print(f"  Max Drawdown:     ${m.max_drawdown:.2f}")
    print(f"  Max Drawdown %:   {m.max_drawdown_pct:.2f}%")
    print(f"  Max DD Duration:  {m.max_drawdown_duration_secs:.0f}s")
    print(f"  Total Trades:     {m.total_trades}")
    print(f"  Win Rate:         {m.win_rate:.1f}%")
    print(f"  Profit Factor:    {m.profit_factor:.2f}")
    print(f"  Expectancy:       ${m.expectancy:.4f}")
    print(f"  Avg Win:          ${m.avg_win:.4f}")
    print(f"  Avg Loss:         ${m.avg_loss:.4f}")
    print(f"  Largest Win:      ${m.largest_win:.4f}")
    print(f"  Largest Loss:     ${m.largest_loss:.4f}")
    print(f"  Total Fees:       ${m.total_fees:.4f}")

run_snippet("BacktestResult - metrics", snippet_result_metrics)


# ---------------------------------------------------------------------------
# Snippet 17: result.summary() (lines 526-527)
# ---------------------------------------------------------------------------
def snippet_result_summary():
    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + (t % 10) * 0.005} for t in range(500)]

    result = hz.backtest(
        markets=["mkt"],
        data=data,
        pipeline=[model, quoter],
    )
    output = result.summary()
    print(output)
    assert isinstance(output, str)
    assert "BACKTEST RESULTS" in output

run_snippet("result.summary()", snippet_result_summary)


# ---------------------------------------------------------------------------
# Snippet 18: result.pnl_by_market() (lines 547-549)
# ---------------------------------------------------------------------------
def snippet_pnl_by_market():
    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + (t % 10) * 0.005} for t in range(500)]

    result = hz.backtest(
        markets=["mkt"],
        data=data,
        pipeline=[model, quoter],
    )

    pnl = result.pnl_by_market()
    for market, realized in pnl.items():
        print(f"  {market}: ${realized:.2f}")

run_snippet("result.pnl_by_market()", snippet_pnl_by_market)


# ---------------------------------------------------------------------------
# Snippet 19: result.equity_curve (lines 557-559)
# ---------------------------------------------------------------------------
def snippet_equity_curve():
    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + (t % 10) * 0.005} for t in range(500)]

    result = hz.backtest(
        markets=["mkt"],
        data=data,
        pipeline=[model, quoter],
    )

    curve = result.equity_curve
    for ts, equity in curve[:5]:
        print(f"  t={ts}: ${equity:.2f}")

run_snippet("result.equity_curve", snippet_equity_curve)


# ---------------------------------------------------------------------------
# Snippet 20: result.trades (lines 567-569)
# ---------------------------------------------------------------------------
def snippet_result_trades():
    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + (t % 10) * 0.005} for t in range(500)]

    result = hz.backtest(
        markets=["mkt"],
        data=data,
        pipeline=[model, quoter],
    )

    for fill in result.trades[:5]:
        print(f"  {fill.side} {fill.order_side} {fill.size} @ {fill.price}")

run_snippet("result.trades", snippet_result_trades)


# ---------------------------------------------------------------------------
# Snippet 21: result.to_csv() (lines 576-580)
# ---------------------------------------------------------------------------
def snippet_to_csv():
    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + (t % 10) * 0.005} for t in range(500)]

    result = hz.backtest(
        markets=["mkt"],
        data=data,
        pipeline=[model, quoter],
    )

    with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as f:
        equity_path = f.name
    with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as f:
        trades_path = f.name

    try:
        result.to_csv(equity_path, what="equity")
        result.to_csv(trades_path, what="trades")
        # Verify files exist and have content
        assert os.path.getsize(equity_path) > 0
        assert os.path.getsize(trades_path) > 0
        print(f"  Equity CSV: {os.path.getsize(equity_path)} bytes")
        print(f"  Trades CSV: {os.path.getsize(trades_path)} bytes")
    finally:
        os.unlink(equity_path)
        os.unlink(trades_path)

run_snippet("result.to_csv()", snippet_to_csv)


# ---------------------------------------------------------------------------
# Snippet 22: Basic Backtest Example (lines 590-625)
# ---------------------------------------------------------------------------
def snippet_basic_backtest():
    import random

    def mean_reversion(ctx):
        price = ctx.feed.price
        fair = 0.50
        return fair

    def quoter(ctx, fair):
        edge = fair - ctx.feed.price
        if abs(edge) < 0.03:
            return None

        return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    random.seed(42)
    price = 0.50
    data = []
    for i in range(1000):
        price += random.gauss(0, 0.01)
        price = max(0.01, min(0.99, price))
        data.append({"timestamp": 1700000000 + i, "price": round(price, 4)})

    result = hz.backtest(
        name="mean-reversion",
        markets=["test-market"],
        data=data,
        pipeline=[mean_reversion, quoter],
        initial_capital=1000.0,
        paper_fee_rate=0.002,
    )

    print(result.summary())

run_snippet("Basic Backtest Example", snippet_basic_backtest)


# ---------------------------------------------------------------------------
# Snippet 23: Multi-Feed Backtest (lines 630-672)
# ---------------------------------------------------------------------------
def snippet_multi_feed_backtest():
    def cross_market_model(ctx):
        signal_price = ctx.feeds["binance"].price
        if signal_price > 0.60:
            return 0.75
        else:
            return 0.35

    def quoter(ctx, fair):
        edge = fair - ctx.feed.price
        if edge > 0.05:
            return hz.quotes(ctx.feed.price, spread=0.04, size=20)
        elif edge < -0.05:
            return hz.quotes(ctx.feed.price, spread=0.04, size=20)

    data = {
        "polymarket_book": [
            {"timestamp": t, "price": 0.50 + (t % 10) * 0.02, "bid": 0.49, "ask": 0.53}
            for t in range(1700000000, 1700000500)
        ],
        "binance": [
            {"timestamp": t, "price": 0.55 + (t % 20) * 0.01}
            for t in range(1700000000, 1700000500)
        ],
    }

    result = hz.backtest(
        name="cross-market",
        markets=["btc-above-100k"],
        data=data,
        feeds={"btc-above-100k": "polymarket_book"},
        pipeline=[cross_market_model, quoter],
        initial_capital=5000.0,
    )

    print(result.summary())
    print("  PnL by market:")
    for market, pnl in result.pnl_by_market().items():
        print(f"    {market}: ${pnl:.2f}")

run_snippet("Multi-Feed Backtest", snippet_multi_feed_backtest)


# ---------------------------------------------------------------------------
# Snippet 24: DataFrame Input (lines 678-704)
# SKIP external CSV file; use synthetic DataFrame instead
# ---------------------------------------------------------------------------
def snippet_dataframe_input():
    try:
        import pandas as pd
    except ImportError:
        print("  (pandas not installed, skipping)")
        return

    # Create synthetic DataFrame instead of loading external file
    df = pd.DataFrame({
        "timestamp": list(range(1700000000, 1700000200)),
        "price": [0.50 + (t % 10) * 0.005 for t in range(200)],
        "bid": [0.49 + (t % 10) * 0.005 for t in range(200)],
        "ask": [0.51 + (t % 10) * 0.005 for t in range(200)],
    })

    assert "timestamp" in df.columns
    assert "price" in df.columns

    def momentum(ctx):
        return ctx.feed.price * 1.01

    def quoter(ctx, fair):
        if fair > ctx.feed.ask:
            return hz.quotes(ctx.feed.ask, spread=0.04, size=5)

    result = hz.backtest(
        name="momentum-df",
        markets=["my-market"],
        data=df,
        pipeline=[momentum, quoter],
    )

    with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as f:
        eq_path = f.name
    with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as f:
        tr_path = f.name

    try:
        result.to_csv(eq_path, what="equity")
        result.to_csv(tr_path, what="trades")
        print(f"  Equity CSV: {os.path.getsize(eq_path)} bytes")
        print(f"  Trades CSV: {os.path.getsize(tr_path)} bytes")
    finally:
        os.unlink(eq_path)
        os.unlink(tr_path)

run_snippet("DataFrame Input Example", snippet_dataframe_input)


# ---------------------------------------------------------------------------
# Snippet 25: Brier Score with Outcomes (lines 712-738)
# ---------------------------------------------------------------------------
def snippet_brier_score():
    def probability_model(ctx):
        return 0.65

    def quoter(ctx, fair):
        if fair > ctx.feed.price + 0.03:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [
        {"timestamp": t, "price": 0.55 + (t % 5) * 0.01}
        for t in range(1700000000, 1700000200)
    ]

    result = hz.backtest(
        name="calibration-test",
        markets=["will-it-rain"],
        data=data,
        pipeline=[probability_model, quoter],
        outcomes={"will-it-rain": 1.0},
    )

    m = result.metrics
    print(f"  Brier Score: {m.brier_score:.4f}" if m.brier_score is not None else "  Brier Score: N/A")
    print(f"  Avg Edge:    {m.avg_edge:.4f}" if m.avg_edge is not None else "  Avg Edge: N/A")
    print(result.summary())

run_snippet("Brier Score with Outcomes", snippet_brier_score)


# ---------------------------------------------------------------------------
# Snippet 26: With Risk Configuration (lines 748-778)
# ---------------------------------------------------------------------------
def snippet_risk_config():
    from horizon import RiskConfig

    risk = RiskConfig(
        max_position_per_market=100.0,
        max_order_size=20.0,
        max_portfolio_notional=5000.0,
        max_daily_drawdown_pct=10.0,
    )

    def model(ctx):
        return 0.60

    def aggressive_quoter(ctx, fair):
        return hz.quotes(ctx.feed.price, spread=0.04, size=50)

    data = [
        {"timestamp": t, "price": 0.50 + (t % 10) * 0.005}
        for t in range(1700000000, 1700001000)
    ]

    result = hz.backtest(
        name="risk-limited",
        markets=["test-market"],
        data=data,
        pipeline=[model, aggressive_quoter],
        risk=risk,
        initial_capital=2000.0,
    )

    print(result.summary())

run_snippet("With Risk Configuration", snippet_risk_config)


# ---------------------------------------------------------------------------
# Snippet 27: Tearsheet (lines 790-813)
# ---------------------------------------------------------------------------
def snippet_tearsheet():
    from horizon import generate_tearsheet

    def model(ctx):
        return ctx.feed.price * 1.02

    def quoter(ctx, fair):
        if fair > ctx.feed.price:
            return hz.quotes(ctx.feed.price, spread=0.04, size=10)

    data = [{"timestamp": t, "price": 0.50 + (t % 10) * 0.005} for t in range(500)]

    result = hz.backtest(
        markets=["mkt"],
        data=data,
        pipeline=[model, quoter],
    )

    tearsheet = result.tearsheet()

    # Also test generate_tearsheet directly with a simple equity curve
    tearsheet2 = generate_tearsheet(
        equity_curve=[(1000, 100), (1001, 101), (1002, 99), (1003, 102), (1004, 105)],
        trades=result.trades if result else [],
        initial_capital=100.0,
    )

    print(f"  monthly_returns: {tearsheet.monthly_returns}")
    print(f"  drawdowns: {len(tearsheet.drawdowns)} periods")
    print(f"  avg_win: {tearsheet.avg_win}")
    print(f"  avg_loss: {tearsheet.avg_loss}")
    print(f"  largest_win: {tearsheet.largest_win}")
    print(f"  largest_loss: {tearsheet.largest_loss}")
    print(f"  win_streak: {tearsheet.win_streak}")
    print(f"  loss_streak: {tearsheet.loss_streak}")
    print(f"  tail_ratio: {tearsheet.tail_ratio}")
    print(f"  time_of_day: {tearsheet.time_of_day}")
    print(f"  rolling_sharpe: {len(tearsheet.rolling_sharpe)} points")
    print(f"  rolling_sortino: {len(tearsheet.rolling_sortino)} points")

run_snippet("Tearsheet", snippet_tearsheet)


# ===========================================================================
# Summary
# ===========================================================================
print("\n" + "=" * 60)
print("  SUMMARY")
print("=" * 60)

passed = sum(1 for _, ok, _ in results if ok)
failed = sum(1 for _, ok, _ in results if not ok)

for name, ok, err in results:
    status = "PASS" if ok else "FAIL"
    line = f"  [{status}] {name}"
    if err:
        line += f" -- {err[:80]}"
    print(line)

print(f"\nTotal: {len(results)} | Passed: {passed} | Failed: {failed}")
sys.exit(0 if failed == 0 else 1)
