"""Tests for act.vectors module — Appendix B test vectors."""

import json
from pathlib import Path

import pytest

from act.token import decode_jws
from act.vectors import generate_vectors, validate_vectors

SCHEMA_PATH = Path(__file__).resolve().parent.parent / "act" / "schema.json"


class TestVectorGeneration:
    def test_generates_15_vectors(self):
        vectors, ctx = generate_vectors()
        assert len(vectors) == 15

    def test_vector_ids(self):
        vectors, _ = generate_vectors()
        ids = [v.id for v in vectors]
        expected = [f"B.{i}" for i in range(1, 16)]
        assert ids == expected

    def test_valid_vectors_have_compact(self):
        vectors, _ = generate_vectors()
        for v in vectors:
            if v.valid and v.id != "B.7":
                assert v.compact, f"{v.id} should have compact"

    def test_invalid_vectors_have_exception(self):
        vectors, _ = generate_vectors()
        for v in vectors:
            if not v.valid:
                assert v.expected_exception is not None, \
                    f"{v.id} should have expected_exception"


class TestVectorValidation:
    def test_all_vectors_pass(self):
        assert validate_vectors() is True


class TestVectorReproducibility:
    def test_compacts_are_deterministic(self):
        # Published Appendix B vectors must be byte-for-byte stable.
        v1, _ = generate_vectors()
        v2, _ = generate_vectors()
        a = {v.id: v.compact for v in v1}
        b = {v.id: v.compact for v in v2}
        assert a == b


class TestSchemaConformance:
    def test_schema_is_well_formed(self):
        jsonschema = pytest.importorskip("jsonschema")
        schema = json.loads(SCHEMA_PATH.read_text())
        jsonschema.Draft202012Validator.check_schema(schema)

    def test_valid_vectors_conform_to_schema(self):
        jsonschema = pytest.importorskip("jsonschema")
        schema = json.loads(SCHEMA_PATH.read_text())
        validator = jsonschema.Draft202012Validator(schema)
        vectors, _ = generate_vectors()
        valid_with_token = {"B.1", "B.2", "B.3", "B.4", "B.5"}
        for v in vectors:
            if v.id in valid_with_token:
                _h, claims, _s, _si = decode_jws(v.compact)
                errors = list(validator.iter_errors(claims))
                assert not errors, f"{v.id}: {errors}"
