"""Unit tests for lexical document validator."""
from __future__ import annotations

import pytest

from blog.bp.blog.ghost.lexical_validator import (
    validate_lexical, ALLOWED_NODE_TYPES,
)


class TestValidateLexical:
    def test_valid_empty_doc(self):
        ok, reason = validate_lexical({"root": {"type": "root", "children": []}})
        assert ok is True
        assert reason is None

    def test_non_dict_input(self):
        ok, reason = validate_lexical("not a dict")
        assert ok is False
        assert "JSON object" in reason

    def test_list_input(self):
        ok, reason = validate_lexical([])
        assert ok is False

    def test_missing_root(self):
        ok, reason = validate_lexical({"foo": "bar"})
        assert ok is False
        assert "'root'" in reason

    def test_root_not_dict(self):
        ok, reason = validate_lexical({"root": "string"})
        assert ok is False

    def test_valid_paragraph(self):
        doc = {"root": {"type": "root", "children": [
            {"type": "paragraph", "children": [
                {"type": "text", "text": "hello"}
            ]}
        ]}}
        ok, _ = validate_lexical(doc)
        assert ok is True

    def test_disallowed_type(self):
        doc = {"root": {"type": "root", "children": [
            {"type": "script"}
        ]}}
        ok, reason = validate_lexical(doc)
        assert ok is False
        assert "Disallowed node type: script" in reason

    def test_nested_disallowed_type(self):
        doc = {"root": {"type": "root", "children": [
            {"type": "paragraph", "children": [
                {"type": "list", "children": [
                    {"type": "evil-widget"}
                ]}
            ]}
        ]}}
        ok, reason = validate_lexical(doc)
        assert ok is False
        assert "evil-widget" in reason

    def test_node_without_type_allowed(self):
        """Nodes with type=None are allowed by _walk."""
        doc = {"root": {"type": "root", "children": [
            {"children": []}  # no "type" key
        ]}}
        ok, _ = validate_lexical(doc)
        assert ok is True

    def test_all_allowed_types(self):
        """Every type in the allowlist should pass."""
        for node_type in ALLOWED_NODE_TYPES:
            doc = {"root": {"type": "root", "children": [
                {"type": node_type, "children": []}
            ]}}
            ok, reason = validate_lexical(doc)
            assert ok is True, f"{node_type} should be allowed but got: {reason}"

    def test_allowed_types_count(self):
        """Sanity: at least 30 types in the allowlist."""
        assert len(ALLOWED_NODE_TYPES) >= 30
