"""树展平器单测：用真实 store/videos/0RxMZBLeqRI/tree.json 验证展平正确性与 fail-loud。"""

import json
from pathlib import Path

import pytest

from app.harness.tree_nodes import load_tree_data_for_videos, load_tree_nodes

_STORE = Path("store")
_VID = "0RxMZBLeqRI"  # 真实样本，111 节点


def _recursive_count(tree_json: dict) -> int:
    def walk(n: dict) -> int:
        return 1 + sum(walk(c) for c in (n.get("children") or []))

    return sum(walk(r) for r in tree_json["roots"])


def test_load_tree_nodes_flattens_all_nodes():
    result = load_tree_nodes(_STORE, _VID)
    assert set(result.keys()) == {"nodes"}
    nodes = result["nodes"]
    raw = json.loads((_STORE / "videos" / _VID / "tree.json").read_text(encoding="utf-8"))
    assert len(nodes) == _recursive_count(raw)
    sample = next(iter(nodes.values()))
    assert set(sample.keys()) == {"card", "level", "time_range"}
    assert isinstance(sample["card"], dict)


def test_level_assigned_by_depth_not_node_id():
    nodes = load_tree_nodes(_STORE, _VID)["nodes"]
    l1_id = f"{_VID}_L1_000"
    l3_id = f"{_VID}_L1_000_L2_000_L3_000"
    assert nodes[l1_id]["level"] == 1
    assert nodes[l3_id]["level"] == 3  # 若按 node_id 首个 _L\d_ 会误判成 1


def test_missing_tree_raises_file_not_found():
    with pytest.raises(FileNotFoundError):
        load_tree_nodes(_STORE, "__no_such_video__")


def test_empty_roots_raises_value_error(tmp_path):
    vdir = tmp_path / "videos" / "vX"
    vdir.mkdir(parents=True)
    (vdir / "tree.json").write_text(json.dumps({"metadata": {}, "roots": []}), encoding="utf-8")
    with pytest.raises(ValueError):
        load_tree_nodes(tmp_path, "vX")


def test_load_for_videos_dedups():
    data = load_tree_data_for_videos(_STORE, [_VID, _VID])
    assert set(data.keys()) == {_VID}
    assert data[_VID]["nodes"]
