"""tests/test_scoring_local_verifier.py — Unit tests for llm_guard.scoring.local_verifier."""
import pytest
import numpy as np

pytestmark = pytest.mark.unit


def _make_run(correct=True):
    return {
        "question": "Who founded Apple?",
        "steps": [
            {"thought": "searching", "action_type": "Search",
             "observation": "Steve Jobs founded Apple.", "action_arg": "Apple founder"},
        ],
        "final_answer": "Steve Jobs",
        "correct": correct,
    }


def _make_runs(n=25):
    return [_make_run(i % 2 == 0) for i in range(n)]


class TestImport:
    def test_import(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        assert LocalVerifier is not None

    def test_import_extract_features(self):
        from llm_guard.scoring.local_verifier import extract_features
        assert callable(extract_features)

    def test_import_feature_names(self):
        from llm_guard.scoring.local_verifier import FEATURE_NAMES
        assert len(FEATURE_NAMES) == 15


class TestInstantiation:
    def test_default_construction(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        assert not v.is_fitted

    def test_custom_params(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier(C=0.5, max_iter=500)
        assert v._C == 0.5


class TestFeatureExtraction:
    def test_shape(self):
        from llm_guard.scoring.local_verifier import extract_features
        run = _make_run()
        feats = extract_features(run["question"], run["steps"], run["final_answer"])
        assert feats.shape == (15,)

    def test_values_finite(self):
        from llm_guard.scoring.local_verifier import extract_features
        run = _make_run()
        feats = extract_features(run["question"], run["steps"], run["final_answer"])
        assert all(np.isfinite(feats))

    def test_empty_steps(self):
        from llm_guard.scoring.local_verifier import extract_features
        feats = extract_features("Who?", [], "No one")
        assert feats.shape == (15,)


class TestFitAndPredict:
    def test_fit_returns_self(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        runs = _make_runs()
        result = v.fit(runs)
        assert result is v

    def test_is_fitted_after_fit(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        v.fit(_make_runs())
        assert v.is_fitted

    def test_n_train(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        runs = _make_runs(25)
        v.fit(runs)
        assert v.n_train == 25

    def test_predict_risk_returns_float(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        v.fit(_make_runs())
        run = _make_run()
        risk = v.predict_risk(run["question"], run["steps"], run["final_answer"])
        assert 0.0 <= risk <= 1.0

    def test_predict_risk_raises_unfitted(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        with pytest.raises(RuntimeError):
            v.predict_risk("Q", [], "A")

    def test_feature_importances(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        v.fit(_make_runs())
        fi = v.feature_importances()
        assert len(fi) == 15
        assert all(val >= 0 for val in fi.values())

    def test_save_load(self, tmp_path):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        v.fit(_make_runs())
        path = str(tmp_path / "verifier.pkl")
        v.save(path)
        loaded = LocalVerifier.load(path)
        assert loaded.is_fitted

    def test_save_raises_unfitted(self, tmp_path):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        with pytest.raises(RuntimeError):
            v.save(str(tmp_path / "v.pkl"))

    def test_repr(self):
        from llm_guard.scoring.local_verifier import LocalVerifier
        v = LocalVerifier()
        r = repr(v)
        assert "LocalVerifier" in r
