import string

import pytest
from hypothesis import HealthCheck, given, settings
from hypothesis import strategies as st
from kdl import Node as KdlNode
from lxml import html as html_parser

from kdlj2_web import render_node_list

alphanum = st.text(
    st.sampled_from(string.ascii_letters + string.digits), min_size=1, max_size=30
)
alphanum_big = st.text(
    st.sampled_from(string.ascii_letters + string.digits), min_size=1, max_size=300
)

html_name = st.from_regex(r"[a-zA-Z][a-zA-Z0-9\-]{0,15}", fullmatch=True)
html_props = st.dictionaries(alphanum, alphanum, min_size=0, max_size=10)
html_args = st.lists(alphanum, min_size=0, max_size=10)

kdl_regular_node_strategy = st.builds(
    KdlNode, name=html_name, args=html_args, props=html_props
)
kdl_passthrough_node_strategy = st.builds(
    KdlNode, name=st.just("-"), args=st.lists(alphanum_big, min_size=1, max_size=10)
)


def kdl_node_tree_strategy():
    return st.recursive(
        st.one_of(kdl_passthrough_node_strategy, kdl_regular_node_strategy),
        lambda children: st.one_of(
            st.builds(
                KdlNode,
                name=html_name,
                props=html_props,
                args=html_args,
                nodes=children,
            ),
        ),
        min_leaves=1,
        max_leaves=30,
    )


def kdl_node_list_strategy():
    return st.recursive(
        st.lists(
            st.one_of(kdl_passthrough_node_strategy, kdl_regular_node_strategy),
            min_size=1,
            max_size=100,
        ),
        lambda children: st.one_of(
            st.lists(
                st.builds(
                    KdlNode,
                    name=html_name,
                    props=st.dictionaries(alphanum, alphanum),
                    args=st.lists(alphanum),
                    nodes=children,
                ),
                min_size=1,
                max_size=20,
            ),
        ),
        min_leaves=1,
        max_leaves=10,
    )


@settings(max_examples=100, suppress_health_check=[HealthCheck.too_slow])
@given(kdl_node_list_strategy())
def test_generated_html_is_parsable(nodes):
    """Stress test the KDL->HTML leavesrenderer against unusual cases."""
    rendered = render_node_list(nodes)

    try:
        html_parser.fromstring(rendered)
    except Exception as e:
        pytest.fail(f"Produced invalid HTML: {rendered}\nError: {e}")
