"""Tests for Issue #112: Oversized bar write guard.

Validates that _guard_bar_spread_invariant() logs wide bars for observability.
The guard is non-blocking (logs instead of raising) since open-anchored
bars can legitimately have wide spreads due to bidirectional movement.
"""

import logging

import pandas as pd


def test_guard_logs_oversized_bar(caplog):
    """Bar with range > 5x threshold should be logged."""
    from opendeviationbar.clickhouse.bulk_operations import _guard_bar_spread_invariant

    # 250 dbps = 0.25%. 5x = 1.25%. Bar with 1% range is within default multiplier.
    # Use multiplier=3 so 0.75% threshold is exceeded by 1.0% range.
    df = pd.DataFrame(
        {
            "Open": [50000.0],
            "High": [50500.0],  # 1.0% range (500/50000)
            "Low": [50000.0],
            "Close": [50450.0],
            "Volume": [10.0],
        }
    )
    with caplog.at_level(
        logging.INFO, logger="opendeviationbar.clickhouse.bulk_operations"
    ):
        _guard_bar_spread_invariant(df, threshold_decimal_bps=250, multiplier=3)
    assert "Wide-open deviation bar" in caplog.text


def test_guard_accepts_valid_bar(caplog):
    """Bar within threshold should not log."""
    from opendeviationbar.clickhouse.bulk_operations import _guard_bar_spread_invariant

    # 250 dbps = 0.25%. 3x = 0.75%. Bar with 0.2% range should pass silently.
    df = pd.DataFrame(
        {
            "Open": [50000.0],
            "High": [50100.0],  # 0.2% range
            "Low": [50000.0],
            "Close": [50090.0],
            "Volume": [10.0],
        }
    )
    with caplog.at_level(
        logging.INFO, logger="opendeviationbar.clickhouse.bulk_operations"
    ):
        _guard_bar_spread_invariant(df, threshold_decimal_bps=250, multiplier=3)
    assert "Wide-open deviation bar" not in caplog.text


def test_guard_skips_when_no_threshold():
    """When threshold_decimal_bps is None, skip validation."""
    from opendeviationbar.clickhouse.bulk_operations import _guard_bar_spread_invariant

    df = pd.DataFrame(
        {
            "Open": [50000.0],
            "High": [60000.0],  # 20% range — would log for any threshold
            "Low": [50000.0],
        }
    )
    # Should not raise
    _guard_bar_spread_invariant(df, threshold_decimal_bps=None)


def test_guard_works_with_lowercase_columns(caplog):
    """Internal DataFrames use lowercase OHLC columns."""
    from opendeviationbar.clickhouse.bulk_operations import _guard_bar_spread_invariant

    df = pd.DataFrame(
        {
            "open": [50000.0],
            "high": [50500.0],  # 1.0% range
            "low": [50000.0],
            "close": [50450.0],
        }
    )
    with caplog.at_level(
        logging.INFO, logger="opendeviationbar.clickhouse.bulk_operations"
    ):
        _guard_bar_spread_invariant(df, threshold_decimal_bps=250, multiplier=3)
    assert "Wide-open deviation bar" in caplog.text


def test_run_write_guards_includes_bar_range(caplog):
    """_run_write_guards() calls _guard_bar_spread_invariant()."""
    from opendeviationbar.clickhouse.bulk_operations import _run_write_guards

    df = pd.DataFrame(
        {
            "Open": [50000.0],
            "High": [50500.0],  # 1.0% range
            "Low": [50000.0],
            "Close": [50450.0],
            "Volume": [10.0],
            "close_time_ms": [1640995200000],
        }
    )
    with caplog.at_level(
        logging.INFO, logger="opendeviationbar.clickhouse.bulk_operations"
    ):
        _run_write_guards(df, threshold_decimal_bps=250)
    # Guard should log but not raise
    # (1.0% range is within default 5x multiplier of 0.25% = 1.25%, so no log expected)
