#!/usr/bin/env python3
"""
Generate YAML test events from Wasot syntax test markdown files.

Parses test cases from markdown, runs wasot on each input,
and converts the JSONL output to the YAML event format used in tests.
"""

import argparse
import json
import subprocess
from pathlib import Path
from typing import Any

import yaml

from parse_syntax_file import MarkdownTestParser


def run_wasot(wasot_bin: str, input_text: str) -> subprocess.CompletedProcess:
    """Run wasot on the given input text."""
    result = subprocess.run(
        [wasot_bin, "-t", "jsonl"],
        input=input_text,
        capture_output=True,
        text=True,
    )
    return result


def jsonl_to_events(data: dict) -> list[dict | str]:
    """Convert nested JSONL block structure to flat event list."""
    events = []
    if data.get("type") == "block":
        _process_block(data, events)
    # Skip non-block types (e.g., errors, documents)
    return events


def _process_block(block: dict, events: list, default_level: int = 1) -> None:
    """Recursively process a block and its content into events."""
    # Build block-started event
    block_started: dict[str, Any] = {}

    block_started["type"] = block["block_type"]

    level = block.get("level", default_level)
    block_started["level"] = level

    # Include void if present
    if block.get("is_void"):
        block_started["void"] = True

    # Only include id if it's not auto-generated (numeric)
    block_id = block.get("id", "")
    if block_id and not block_id.isdigit():
        block_started["id"] = block_id

    # Include inline-text if present
    if block.get("inline_text"):
        block_started["inline-text"] = block["inline_text"]["content"]

    # Include args if present
    if block.get("args"):
        block_started["args"] = [arg["content"] for arg in block["args"]]

    # Include kwargs if present
    if block.get("kwargs"):
        kwargs = {}
        for kv in block["kwargs"]:
            key = kv[0]["content"]
            value = kv[1]["content"]
            kwargs[key] = value
        block_started["kwargs"] = kwargs

    events.append({"block-started": block_started})

    # Process content
    for child in block.get("content", []):
        if child["type"] == "text":
            events.append({"text-finished": {"lines": child["lines"]}})
        elif child["type"] == "block":
            _process_block(child, events, default_level=level + 1)

    events.append("block-finished")


def events_to_yaml(events: list) -> str:
    """Convert events list to YAML string."""
    return yaml.dump(events, default_flow_style=None, allow_unicode=True, sort_keys=False)


def main():
    parser = argparse.ArgumentParser(
        description="Generate YAML test events from Wasot syntax test markdown files."
    )
    parser.add_argument("input", type=Path, help="Input markdown file with test cases")
    parser.add_argument(
        "--wasot",
        default="wasot",
        help="Path to wasot binary (default: wasot)",
    )

    args = parser.parse_args()

    content = args.input.read_text()
    md_parser = MarkdownTestParser(content)
    test_cases = md_parser.parse()

    print(f"Found {len(test_cases)} test cases\n")

    for i, tc in enumerate(test_cases, 1):
        print(f"[{i}] {tc.name}")
        if tc.chapter:
            print(f"    Chapter: {tc.chapter}")

        result = run_wasot(args.wasot, tc.input)

        if result.returncode != 0:
            print(f"    ERROR (exit {result.returncode}):")
            if result.stderr:
                for line in result.stderr.strip().split('\n'):
                    print(f"      {line}")
        else:
            # Parse JSONL and convert to events
            all_events = []
            for line in result.stdout.strip().split('\n'):
                if line:
                    data = json.loads(line)
                    events = jsonl_to_events(data)
                    all_events.extend(events)

            yaml_output = events_to_yaml(all_events)
            print("    Generated YAML:")
            for line in yaml_output.strip().split('\n'):
                print(f"      {line}")

        print()


if __name__ == "__main__":
    main()
