"""
Discover Playwright tests (.spec.ts files).
"""

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


@dataclass
class PlaywrightTestInfo:
    """Information about a discovered Playwright test."""
    id: str
    name: str
    file_path: str
    test_name: str
    description: Optional[str] = None
    gherkin_feature: Optional[str] = None
    gherkin_scenario: Optional[str] = None
    tags: list[str] = None

    def __post_init__(self):
        if self.tags is None:
            self.tags = []


def discover_playwright_tests(tests_dir: Path) -> list[PlaywrightTestInfo]:
    """
    Discover all Playwright tests in the frontend-tests directory.

    Parses .spec.ts files to extract:
    - test() calls
    - describe() blocks
    - Gherkin metadata from comments
    - Tags from comments
    """
    if not tests_dir.exists():
        return []

    tests = []

    # Find all .spec.ts files
    for spec_file in tests_dir.rglob("*.spec.ts"):
        relative_path = spec_file.relative_to(tests_dir)

        # Read file content
        try:
            content = spec_file.read_text()
        except Exception:
            continue

        # Extract describe blocks and tests
        tests_in_file = _parse_playwright_file(content, spec_file, relative_path)
        tests.extend(tests_in_file)

    return tests


def _parse_playwright_file(
    content: str,
    file_path: Path,
    relative_path: Path
) -> list[PlaywrightTestInfo]:
    """Parse a Playwright test file to extract test information."""
    tests = []

    # Pattern to match test() calls
    # test('test name', async ({ page }) => { ... })
    # test.only('test name', ...)
    test_pattern = re.compile(
        r"test(?:\.\w+)?\s*\(\s*['\"]([^'\"]+)['\"]",
        re.MULTILINE
    )

    # Pattern to match describe() blocks
    describe_pattern = re.compile(
        r"describe\s*\(\s*['\"]([^'\"]+)['\"]",
        re.MULTILINE
    )

    # Extract metadata from comments above tests
    # Looking for JSDoc-style comments with metadata
    metadata_pattern = re.compile(
        r"/\*\*\s*\n((?:\s*\*.*\n)+)\s*\*/\s*\n\s*test",
        re.MULTILINE
    )

    # Find all describe blocks to use as context
    describes = describe_pattern.findall(content)
    describe_context = describes[0] if describes else None

    # Find all tests
    for match in test_pattern.finditer(content):
        test_name = match.group(1)

        # Look for metadata comment before this test
        # Search backwards from the match position
        before_test = content[:match.start()]
        metadata_match = None
        for m in metadata_pattern.finditer(before_test):
            metadata_match = m

        # Parse metadata if found
        gherkin_feature = None
        gherkin_scenario = None
        tags = []
        description = None

        if metadata_match:
            metadata_block = metadata_match.group(1)

            # Extract Feature, Scenario, Tags from metadata
            feature_match = re.search(r"\*\s*Feature:\s*(.+)", metadata_block)
            scenario_match = re.search(r"\*\s*Scenario:\s*(.+)", metadata_block)
            tags_match = re.search(r"\*\s*Tags:\s*(.+)", metadata_block)
            desc_match = re.search(r"\*\s*@description\s+(.+)", metadata_block)

            if feature_match:
                gherkin_feature = feature_match.group(1).strip()
            if scenario_match:
                gherkin_scenario = scenario_match.group(1).strip()
            if tags_match:
                tags_str = tags_match.group(1).strip()
                tags = [t.strip() for t in re.findall(r"@[\w-]+", tags_str)]
            if desc_match:
                description = desc_match.group(1).strip()

        # Build test ID
        module_name = str(relative_path).replace("/", ".").replace(".spec.ts", "")
        test_id = f"frontend.{module_name}.{_sanitize_test_name(test_name)}"

        tests.append(PlaywrightTestInfo(
            id=test_id,
            name=test_name,
            file_path=str(relative_path),
            test_name=test_name,
            description=description or test_name,
            gherkin_feature=gherkin_feature,
            gherkin_scenario=gherkin_scenario,
            tags=tags,
        ))

    return tests


def _sanitize_test_name(name: str) -> str:
    """Convert test name to a valid identifier."""
    # Replace spaces and special chars with underscores
    sanitized = re.sub(r"[^\w]+", "_", name.lower())
    # Remove leading/trailing underscores
    sanitized = sanitized.strip("_")
    return sanitized
