"""tests/test_verification_chart_validator.py — Unit tests for ChartValidator."""
import pytest

pytestmark = pytest.mark.unit

SPEC = {
    "mark": "bar",
    "encoding": {
        "x": {"field": "month", "type": "ordinal"},
        "y": {"field": "revenue", "type": "quantitative"},
    },
}
DATA = [
    {"month": "Jan", "revenue": 12000},
    {"month": "Feb", "revenue": 15400},
]


class TestImport:
    def test_import_validator(self):
        from llm_guard.verification.chart_validator import ChartValidator
        assert ChartValidator is not None

    def test_import_result(self):
        from llm_guard.verification.chart_validator import ChartValidationResult
        assert ChartValidationResult is not None


class TestChartValidatorInstantiation:
    def test_no_key_construction(self):
        from llm_guard.verification.chart_validator import ChartValidator
        v = ChartValidator(api_key="")
        assert v._client is None

    def test_model_stored(self):
        from llm_guard.verification.chart_validator import ChartValidator
        v = ChartValidator(api_key="", model="claude-haiku-4-5-20251001")
        assert "haiku" in v._model


class TestHeuristicValidation:
    """Tests for the zero-cost heuristic fallback."""

    def _validate(self, question, spec, data=None):
        from llm_guard.verification.chart_validator import ChartValidator
        v = ChartValidator(api_key="")
        return v.validate(question, spec, data_sample=data)

    def test_valid_bar_comparison(self):
        result = self._validate("Compare revenue by month", SPEC, DATA)
        assert result.verdict in ("VALID", "UNCERTAIN")
        assert 0.0 <= result.risk_score <= 1.0

    def test_wrong_chart_type_for_trend(self):
        result = self._validate("Show monthly revenue trend over time", SPEC, DATA)
        # Bar chart for a trend question may be flagged
        assert isinstance(result.issues, list)

    def test_scatter_for_correlation(self):
        spec = {"mark": "scatter", "encoding": {"x": {"field": "x"}, "y": {"field": "y"}}}
        result = self._validate("Correlation between x and y", spec, [{"x": 1, "y": 2}])
        assert result.verdict in ("VALID", "UNCERTAIN")

    def test_missing_fields_in_encoding(self):
        bad_spec = {
            "mark": "bar",
            "encoding": {
                "x": {"type": "ordinal"},  # missing "field"
            }
        }
        result = self._validate("Compare things", bad_spec)
        assert isinstance(result.issues, list)

    def test_field_not_in_data_flagged(self):
        spec_with_wrong_field = {
            "mark": "bar",
            "encoding": {
                "x": {"field": "nonexistent_col", "type": "ordinal"},
                "y": {"field": "revenue", "type": "quantitative"},
            },
        }
        result = self._validate("Monthly revenue", spec_with_wrong_field, DATA)
        # Should flag that field 'nonexistent_col' is not in data
        assert len(result.issues) > 0 or result.verdict in ("UNCERTAIN", "INVALID")

    def test_judge_model_heuristic(self):
        result = self._validate("Q", SPEC, DATA)
        assert result.judge_model == "heuristic"

    def test_string_spec(self):
        result = self._validate("Show a bar chart of results", "bar chart of results")
        assert result.verdict in ("VALID", "UNCERTAIN", "INVALID")

    def test_validate_batch(self):
        from llm_guard.verification.chart_validator import ChartValidator
        v = ChartValidator(api_key="")
        items = [
            {"question": "Q1", "chart_spec": SPEC, "data_sample": DATA},
            {"question": "Q2", "chart_spec": {"mark": "line", "encoding": {}}},
        ]
        results = v.validate_batch(items)
        assert len(results) == 2

    def test_risk_score_valid_is_low(self):
        result = self._validate("Compare monthly revenue", SPEC, DATA)
        if result.verdict == "VALID":
            assert result.risk_score == pytest.approx(0.10, abs=0.01)

    def test_no_data_sample(self):
        result = self._validate("Q", SPEC, data=None)
        assert result.verdict in ("VALID", "UNCERTAIN", "INVALID")
