import pytest

from tools import run_mlp_adaptive as adaptive


def evidence(calmar=1.0, fingerprint="same"):
    return {"Calmar Ratio": calmar, "Comparison_Fingerprint": fingerprint}


def test_adaptive_uses_replay_not_stored_metrics(monkeypatch):
    monkeypatch.setattr(adaptive, "read_winner_evidence", lambda *args: evidence(1.25))
    assert adaptive.read_winner_calmar("BTC", "6H") == 1.25


def test_failed_replay_is_not_zero(monkeypatch):
    def fail(*args):
        raise ValueError("incumbent incomplete")
    monkeypatch.setattr(adaptive, "read_winner_evidence", fail)
    with pytest.raises(ValueError, match="incomplete"):
        adaptive.read_winner_calmar("BTC", "6H")


def test_progress_requires_same_context():
    state = adaptive.TFState("6H", comparison_fingerprint="same", last_calmar=1.)
    assert adaptive.comparison_delta(state, evidence(), evidence(1.1)) == pytest.approx(.1)
    with pytest.raises(ValueError, match="fingerprint"):
        adaptive.comparison_delta(state, evidence(), evidence(2., "changed-data"))
    with pytest.raises(ValueError, match="reproduce"):
        adaptive.comparison_delta(state, evidence(1.2), evidence(1.3))


@pytest.mark.parametrize("calmar", [float("nan"), float("inf")])
def test_nonfinite_replay_cannot_count_as_progress(calmar):
    state = adaptive.TFState("6H", comparison_fingerprint="same", last_calmar=1.)
    with pytest.raises(ValueError, match="finite"):
        adaptive.comparison_delta(state, evidence(), evidence(calmar))


def test_failed_sweep_does_not_become_convergence(tmp_path, monkeypatch):
    monkeypatch.setattr(adaptive, "WEIGHTS_DIR", tmp_path)
    state = adaptive.TFState("6H", comparison_fingerprint="same")
    with pytest.raises(RuntimeError, match="convergence not measured"):
        adaptive.sweep_round("BTC", [state], "bb50", 1, False)
    assert state.no_improve_rounds == 0


def test_sweep_passes_locked_context_to_subprocess(tmp_path, monkeypatch):
    (tmp_path / "mlp_weights_BTC_6H_bb50_seed101.json").write_text("{}")
    monkeypatch.setattr(adaptive, "WEIGHTS_DIR", tmp_path)
    calls = []

    def run(command, **kwargs):
        calls.append(command)
        return type("Result", (), {"returncode": 0})()

    monkeypatch.setattr(adaptive.subprocess, "run", run)
    adaptive.sweep_round("BTC", [adaptive.TFState("6H", comparison_fingerprint="locked", incumbent_identity="model-and-params")],
                         "bb50", 1, False)
    index = calls[0].index("--expected-comparison-fingerprint")
    assert calls[0][index + 1] == "locked"
    index = calls[0].index("--expected-incumbent-identity")
    assert calls[0][index + 1] == "model-and-params"
