import json
from pathlib import Path

from app.canon_log import validate_canon_log

FIXTURE = Path(__file__).parent / "fixtures" / "canon_log_valid.json"


def _valid():
    with open(FIXTURE) as f:
        return json.load(f)


def test_valid_canon_log_passes():
    assert validate_canon_log(_valid()) == []


def test_numeric_luck_is_rejected():
    # Charter §7: the AI must never be able to calculate Luck. A stray numeric
    # luck field must fail validation, not slip through.
    doc = _valid()
    doc["player"]["luck"] = 5
    assert validate_canon_log(doc) != []


def test_recent_events_over_five_is_rejected():
    doc = _valid()
    doc["recent_events"] = [f"event {i}" for i in range(6)]
    assert validate_canon_log(doc) != []


def test_disposition_out_of_range_is_rejected():
    doc = _valid()
    doc["party"][0]["disposition"] = 200
    assert validate_canon_log(doc) != []


def test_unknown_quest_status_is_rejected():
    doc = _valid()
    doc["active_quests"][0]["status"] = "abandoned"
    assert validate_canon_log(doc) != []


def test_humiliation_weight_bounds_enforced():
    doc = _valid()
    doc["humiliations"][0]["weight"] = 11
    assert validate_canon_log(doc) != []


def test_empty_optional_arrays_are_allowed():
    doc = _valid()
    doc["party"] = []
    doc["recent_events"] = []
    doc["established_facts"] = []
    doc["active_quests"] = []
    doc["humiliations"] = []
    assert validate_canon_log(doc) == []


def test_root_level_stray_field_is_rejected():
    # §2/§7: stats/HP/inventory must never enter the log — additionalProperties:false at root.
    doc = _valid()
    doc["hp"] = 10
    assert validate_canon_log(doc) != []


def test_negative_turn_is_rejected():
    doc = _valid()
    doc["humiliations"][0]["turn"] = -1
    assert validate_canon_log(doc) != []
