"""
Parse Wasot syntax test markdown files into TestCase objects.

This module provides parsing logic for markdown files containing test cases
with wasot input blocks and yaml expected events.
"""

import re
import sys
import yaml
from typing import List, Dict, Any, Optional
from dataclasses import dataclass


@dataclass
class TestCase:
    """Represents a single test case."""
    name: str
    description: str
    input: str
    expected_events: List[Dict[str, Any]]
    chapter: str = ""
    section_number: int = 0


class MarkdownTestParser:
    """Parser for markdown test files."""

    def __init__(self, content: str):
        self.content = content
        self.lines = content.split('\n')
        self.current_line = 0
        self.current_chapter = ""
        self.section_counter = 0

    def parse(self) -> List[TestCase]:
        """Parse all test cases from the markdown content."""
        test_cases = []

        while self.current_line < len(self.lines):
            line = self.lines[self.current_line]

            # Check for chapter heading (## Chapter N: ...) or any ## heading
            if line.startswith('## '):
                self.current_chapter = self._extract_chapter_name(line)
                self.section_counter = 0
                self.current_line += 1
                continue

            # Check for test case (starts with **)
            if line.startswith('**') and line.endswith('**') and len(line) > 4:
                test_case = self._parse_test_case()
                if test_case:
                    test_case.chapter = self.current_chapter
                    test_case.section_number = self.section_counter
                    test_cases.append(test_case)
                    self.section_counter += 1
                # Note: _parse_test_case advances current_line
            else:
                self.current_line += 1

        return test_cases

    def _extract_chapter_name(self, line: str) -> str:
        """Extract chapter name from heading."""
        # Remove ## and extract chapter name
        match = re.match(r'## Chapter \d+: (.+)', line)
        if match:
            return match.group(1)
        return line.replace('## ', '')

    def _parse_test_case(self) -> Optional[TestCase]:
        """Parse a single test case starting at current line."""
        # Extract test name
        line = self.lines[self.current_line]
        name = line[2:-2]  # Remove ** from both ends
        self.current_line += 1


        # Skip empty line if present
        if self.current_line < len(self.lines) and not self.lines[self.current_line].strip():
            self.current_line += 1

        # Collect description until we hit code block
        description_lines = []
        while self.current_line < len(self.lines):
            line = self.lines[self.current_line]

            # Stop at next test case or code block or heading
            if line.startswith('```wasot') or (line.startswith('**') and line.endswith('**')) or line.startswith('#'):
                break

            # Skip separator lines
            if line.strip() != '---':
                description_lines.append(line)
            self.current_line += 1

        description = '\n'.join(description_lines).strip()

        # Parse wasot input block
        if not self._expect_line('```wasot'):
            return None

        input_lines = []
        while self.current_line < len(self.lines):
            line = self.lines[self.current_line]
            self.current_line += 1
            if line.startswith('```'):
                break
            input_lines.append(line)

        input_text = '\n'.join(input_lines)

        # Skip empty line between blocks if present
        if self.current_line < len(self.lines) and not self.lines[self.current_line].strip():
            self.current_line += 1

        # Parse yaml expected events block
        if not self._expect_line('```yaml'):
            return None

        yaml_lines = []
        while self.current_line < len(self.lines):
            line = self.lines[self.current_line]
            self.current_line += 1
            if line.startswith('```'):
                break
            yaml_lines.append(line)

        yaml_text = '\n'.join(yaml_lines)

        # Parse YAML
        try:
            expected_events = yaml.safe_load(yaml_text) or []
        except yaml.YAMLError as e:
            print(f"Error parsing YAML for test '{name}': {e}", file=sys.stderr)
            return None

        # Skip separator if present
        if self.current_line < len(self.lines) and self.lines[self.current_line].strip() == '---':
            self.current_line += 1

        return TestCase(
            name=name,
            description=description,
            input=input_text,
            expected_events=expected_events,
            chapter=self.current_chapter,
            section_number=self.section_counter
        )

    def _expect_line(self, expected: str) -> bool:
        """Check if current line matches expected string."""
        if self.current_line >= len(self.lines):
            return False

        line = self.lines[self.current_line]
        if line.startswith(expected):
            self.current_line += 1
            return True
        return False
