"""Tests para chunk_ax_tree."""

import json
import sys
import os

sys.path.insert(0, os.path.dirname(__file__))

from chunk_ax_tree import chunk_ax_tree


def _node(node_id: str, child_ids=None) -> dict:
    return {
        "nodeId": node_id,
        "role": {"value": "generic"},
        "name": {"value": f"node-{node_id}"},
        "childIds": child_ids or [],
    }


def _make_linear_tree(n: int) -> list[dict]:
    """Cadena lineal: 0->1->2->...->n-1"""
    nodes = []
    for i in range(n):
        child = [str(i + 1)] if i < n - 1 else []
        nodes.append(_node(str(i), child))
    return nodes


def test_lista_vacia_devuelve_lista_vacia():
    result = chunk_ax_tree([])
    assert result == [], f"Expected [], got {result}"


def test_nodos_que_caben_en_un_chunk_devuelven_un_solo_chunk():
    nodes = _make_linear_tree(3)
    result = chunk_ax_tree(nodes, max_chars=10000)
    assert len(result) == 1, f"Expected 1 chunk, got {len(result)}"
    # Todos los nodos deben estar presentes
    ids_in_chunk = [n["nodeId"] for n in result[0]]
    for node in nodes:
        assert node["nodeId"] in ids_in_chunk, f"{node['nodeId']} missing from chunk"


def test_nodos_que_no_caben_generan_multiples_chunks():
    # 100 nodos, cada uno ~80 chars serializado -> ~8000 chars total
    # con max_chars=200 debe generar varios chunks
    nodes = [_node(str(i)) for i in range(100)]
    # Hacer árbol plano: raíz con todos como hijos
    nodes[0]["childIds"] = [str(i) for i in range(1, 100)]
    result = chunk_ax_tree(nodes, max_chars=200)
    assert len(result) > 1, f"Expected >1 chunks, got {len(result)}"


def test_cada_chunk_serializado_no_supera_max_chars_mas_overhead():
    nodes = [_node(str(i)) for i in range(100)]
    nodes[0]["childIds"] = [str(i) for i in range(1, 100)]
    max_chars = 500
    result = chunk_ax_tree(nodes, max_chars=max_chars)
    overhead_factor = 1.5  # permitir 50% de overhead por nodo contexto
    for i, chunk in enumerate(result):
        serialized = json.dumps(chunk, ensure_ascii=False)
        limit = max_chars * overhead_factor
        assert len(serialized) < limit, (
            f"Chunk {i} tiene {len(serialized)} chars, supera {limit} "
            f"(max_chars={max_chars}, overhead_factor={overhead_factor})"
        )


if __name__ == "__main__":
    test_lista_vacia_devuelve_lista_vacia()
    test_nodos_que_caben_en_un_chunk_devuelven_un_solo_chunk()
    test_nodos_que_no_caben_generan_multiples_chunks()
    test_cada_chunk_serializado_no_supera_max_chars_mas_overhead()
    print("All tests passed.")
