#!/usr/bin/env python3
"""Validates transition nodes in KQ4 room scenes."""

import re
import sys
from pathlib import Path
from dataclasses import dataclass
from typing import Optional


@dataclass
class Transition:
    exit_node_name: str
    target_uid: str
    appear_at_node: str
    label: str
    source_room: str


@dataclass
class SceneInfo:
    uid: str
    path: Path
    node_names: set[str]


def find_uid_files(root: Path) -> dict[str, Path]:
    """Build a mapping of UID -> file path from all .uid files."""
    uid_map = {}
    for uid_file in root.rglob("*.uid"):
        uid_content = uid_file.read_text().strip()
        if uid_content.startswith("uid://"):
            resource_path = uid_file.with_suffix("")
            if resource_path.exists():
                uid_map[uid_content] = resource_path
            else:
                uid_map[uid_content] = uid_file.with_suffix("")
    return uid_map


def parse_scene_file(tscn_path: Path) -> tuple[Optional[str], set[str], list[Transition]]:
    """Parse a .tscn file to extract UID, node names, and transitions."""
    content = tscn_path.read_text()
    
    scene_uid = None
    uid_match = re.search(r'\[gd_scene[^\]]*uid="([^"]+)"', content)
    if uid_match:
        scene_uid = uid_match.group(1)
    
    node_names = set(re.findall(r'^\[node name="([^"]+)"', content, re.MULTILINE))
    
    transitions = []
    room_name = tscn_path.stem
    
    transition_pattern = re.compile(
        r'\[node name="([^"]+)"[^\]]*instance=ExtResource\([^\)]+\)\]\s*\n'
        r'((?:[^\[]+\n)*)',
        re.MULTILINE
    )
    
    for match in transition_pattern.finditer(content):
        node_name = match.group(1)
        body = match.group(2)
        
        target_match = re.search(r'^target = "([^"]+)"', body, re.MULTILINE)
        appear_match = re.search(r'^appear_at_node = "([^"]+)"', body, re.MULTILINE)
        label_match = re.search(r'^label = "([^"]+)"', body, re.MULTILINE)
        
        if target_match and appear_match:
            transitions.append(Transition(
                exit_node_name=node_name,
                target_uid=target_match.group(1),
                appear_at_node=appear_match.group(1),
                label=label_match.group(1) if label_match else node_name,
                source_room=room_name
            ))
    
    return scene_uid, node_names, transitions


def main():
    root = Path(__file__).parent.parent
    scenes_dir = root / "scenes"
    
    uid_map = find_uid_files(root)
    
    scene_files = list(scenes_dir.glob("kq4_*/kq4_*.tscn"))
    scene_files = [f for f in scene_files if "placeholder_template" not in str(f)]
    
    scenes_by_uid: dict[str, SceneInfo] = {}
    all_transitions: list[Transition] = []
    
    for scene_file in scene_files:
        scene_uid, node_names, transitions = parse_scene_file(scene_file)
        if scene_uid:
            scenes_by_uid[scene_uid] = SceneInfo(
                uid=scene_uid,
                path=scene_file,
                node_names=node_names
            )
        all_transitions.extend(transitions)
    
    errors = 0
    
    for t in all_transitions:
        source_room = t.source_room
        target_scene = scenes_by_uid.get(t.target_uid)
        
        if target_scene is None:
            print(f"ERROR: {source_room} exit '{t.exit_node_name}' -> target UID '{t.target_uid}' NOT FOUND")
            errors += 1
            continue
        
        target_room_name = target_scene.path.stem
        
        if t.appear_at_node not in target_scene.node_names:
            print(f"ERROR: {source_room} exit '{t.exit_node_name}' -> {target_room_name} node '{t.appear_at_node}' NOT FOUND")
            errors += 1
            continue
        
        print(f"OK: {source_room} exit '{t.exit_node_name}' -> {target_room_name} (node: {t.appear_at_node})")
    
    print(f"\n{'='*60}")
    print(f"Checked {len(all_transitions)} transitions across {len(scene_files)} rooms")
    
    if errors:
        print(f"FOUND {errors} ERROR(S)")
        sys.exit(1)
    else:
        print("All transitions valid!")
        sys.exit(0)


if __name__ == "__main__":
    main()
