"""Tests for xmldev.schema — schema loader and AST."""
from __future__ import annotations

import json
import pytest

from xmldev.schema import SchemaLoadError, SchemaLoader


MINIMAL_SCHEMA = {"root": {"name": "order"}}


def test_load_minimal_schema():
    schema = SchemaLoader.load(json.dumps(MINIMAL_SCHEMA))
    assert schema.root.name == "order"


def test_load_from_string():
    schema = SchemaLoader.load(json.dumps(MINIMAL_SCHEMA))
    assert schema.root.name == "order"


def test_load_full_person_schema(person_schema_dict):
    schema = SchemaLoader.load(json.dumps(person_schema_dict))
    assert schema.root.name == "person"
    assert len(schema.root.children) == 3
    age_child = schema.root.children[1]
    assert age_child.spec.name == "age"
    assert age_child.spec.text_type == "int"
    assert age_child.spec.default == 0


def test_aliases_loaded(person_schema_dict):
    schema = SchemaLoader.load(json.dumps(person_schema_dict))
    name_child = schema.root.children[0]
    assert "fullname" in name_child.spec.aliases
    assert "full-name" in name_child.spec.aliases


def test_required_attr_loaded(person_schema_dict):
    schema = SchemaLoader.load(json.dumps(person_schema_dict))
    id_attr = schema.root.attrs["id"]
    assert id_attr.required is True
    assert id_attr.type == "int"


def test_missing_root_raises():
    with pytest.raises(SchemaLoadError, match="XM01"):
        SchemaLoader.load(json.dumps({"global": {}}))


def test_invalid_json_raises():
    with pytest.raises(SchemaLoadError, match="XM01"):
        SchemaLoader.load("{not valid json}")


def test_invalid_text_type_raises():
    bad = {"root": {"name": "x", "text_type": "banana"}}
    with pytest.raises(SchemaLoadError, match="XM01"):
        SchemaLoader.load(json.dumps(bad))


def test_global_fuzzy_config():
    schema_dict = {
        "root": {"name": "x"},
        "global": {
            "allow_unknown": "drop",
            "fuzzy": {"name_threshold": 0.9, "max_renames_per_doc": 5},
        },
    }
    schema = SchemaLoader.load(json.dumps(schema_dict))
    assert schema.global_config.allow_unknown == "drop"
    assert schema.global_config.name_threshold == 0.9
    assert schema.global_config.max_renames_per_doc == 5


def test_conditional_rules_loaded():
    schema_dict = {
        "root": {
            "name": "item",
            "conditional_rules": [{"when": "element.status == 'active'", "then": "True"}],
        }
    }
    schema = SchemaLoader.load(json.dumps(schema_dict))
    assert len(schema.root.conditional_rules) == 1
    assert "active" in schema.root.conditional_rules[0].when


def test_enum_values_loaded():
    schema_dict = {
        "root": {"name": "status", "text_type": "enum", "enum_values": ["active", "inactive"]}
    }
    schema = SchemaLoader.load(json.dumps(schema_dict))
    assert schema.root.enum_values == ["active", "inactive"]


def test_extension_element_default():
    schema = SchemaLoader.load(json.dumps(MINIMAL_SCHEMA))
    assert schema.global_config.extension_element_name == "extensions"
