"""
Platform validation: Test filename generation from acceptance URNs.

Validates that actual test files in the repository follow the URN-based
naming convention for all supported languages.

Spec: SPEC-TESTER-CONV-0069 through SPEC-TESTER-CONV-0078
URN: acc:coach:platform-validation.filename-mapping
"""

import os
import re
from pathlib import Path
import pytest

import atdd
from atdd.coach.utils.repo import find_repo_root


REPO_ROOT = find_repo_root()

# Package resources
ATDD_PKG_DIR = Path(atdd.__file__).resolve().parent


# SPEC-TESTER-CONV-0069: Dart URN to filename mapping
def test_dart_urn_to_filename():
    """Test Dart filename generation from URN."""
    from atdd.tester.utils.filename import dart_filename

    test_cases = [
        ("acc:maintain-ux:C004-E2E-019-user-connection", "C004_E2E_019_user_connection_test.dart"),
        ("acc:maintain-ux:C004-UNIT-001", "C004_UNIT_001_test.dart"),
        ("acc:stage-characters:K005-WIDGET-012-avatar-display", "K005_WIDGET_012_avatar_display_test.dart"),
    ]

    for urn, expected in test_cases:
        assert dart_filename(urn) == expected


# SPEC-TESTER-CONV-0070: TypeScript URN to filename mapping
def test_typescript_urn_to_filename():
    """Test TypeScript filename generation from URN."""
    from atdd.tester.utils.filename import typescript_filename

    test_cases = [
        ("acc:maintain-ux:C004-E2E-019-user-connection", "c004-e2e-019-user-connection.test.ts"),
        ("acc:maintain-ux:C004-HTTP-001", "c004-http-001.test.ts"),
        ("acc:resolve-dilemmas:R007-EVENT-005-choice-made", "r007-event-005-choice-made.test.ts"),
    ]

    for urn, expected in test_cases:
        assert typescript_filename(urn) == expected


# SPEC-TESTER-CONV-0071: Python URN to filename mapping
def test_python_urn_to_filename():
    """Test Python filename generation from URN."""
    from atdd.tester.utils.filename import python_filename

    test_cases = [
        ("acc:maintain-ux:C004-E2E-019-user-connection", "test_c004_e2e_019_user_connection.py"),
        ("acc:commit-state:D001-UNIT-042", "test_d001_unit_042.py"),
        ("acc:construct-graph:M008-INTEGRATION-007-graph-build", "test_m008_integration_007_graph_build.py"),
    ]

    for urn, expected in test_cases:
        assert python_filename(urn) == expected


# SPEC-TESTER-CONV-0072: Go URN to filename mapping
def test_go_urn_to_filename():
    """Test Go filename generation from URN."""
    from atdd.tester.utils.filename import go_filename

    test_cases = [
        ("acc:maintain-ux:C004-E2E-019-user-connection", "c004_e2e_019_user_connection_test.go"),
        ("acc:commit-state:D001-UNIT-042", "d001_unit_042_test.go"),
    ]

    for urn, expected in test_cases:
        assert go_filename(urn) == expected


# SPEC-TESTER-CONV-0073: Java/Kotlin URN to classname mapping
def test_java_urn_to_classname():
    """Test Java/Kotlin classname generation from URN."""
    from atdd.tester.utils.filename import java_classname

    test_cases = [
        ("acc:maintain-ux:C004-E2E-019-user-connection", "C004E2E019UserConnectionTest"),
        ("acc:commit-state:D001-UNIT-042", "D001UNIT042Test"),
        ("acc:stage-characters:K005-INTEGRATION-003-full-flow", "K005INTEGRATION003FullFlowTest"),
    ]

    for urn, expected in test_cases:
        assert java_classname(urn) == expected


# SPEC-TESTER-CONV-0074: Handle URNs without slug
def test_no_slug_handling():
    """Test filename generation for URNs without optional slug."""
    from atdd.tester.utils.filename import dart_filename, typescript_filename, python_filename

    urn = "acc:maintain-ux:C004-E2E-019"

    assert dart_filename(urn) == "C004_E2E_019_test.dart"
    assert typescript_filename(urn) == "c004-e2e-019.test.ts"
    assert python_filename(urn) == "test_c004_e2e_019.py"


def test_typescript_preact_urn_to_filename():
    """Test Preact TypeScript filename generation from URN."""
    from atdd.tester.utils.filename import typescript_preact_filename

    test_cases = [
        ("acc:maintain-ux:C004-E2E-019-user-connection", "C004_E2E_019_user_connection.test.ts"),
        ("acc:maintain-ux:C004-HTTP-001", "C004_HTTP_001.test.ts"),
        ("acc:maintain-ux:C001-WIDGET-001-button", "C001_WIDGET_001_button.test.tsx"),
    ]

    for urn, expected in test_cases:
        assert typescript_preact_filename(urn) == expected


# SPEC-TESTER-CONV-0076: URN pattern validation
def test_urn_pattern_validation():
    """Test URN regex pattern matches valid acceptance URNs."""
    from atdd.tester.utils.filename import URN_PATTERN

    valid_urns = [
        "acc:maintain-ux:C004-E2E-019-user-connection",
        "acc:pace-dilemmas:P003-UNIT-042",
        "acc:predict-cascade:L009-HTTP-001-api-endpoint",
        "acc:commit-state:D001-EVENT-005",
    ]

    for urn in valid_urns:
        assert re.match(URN_PATTERN, urn), f"Should match: {urn}"

    invalid_urns = [
        "acc:maintain_ux:C004-E2E-019",  # Underscore not allowed
        "wmbt:maintain-ux:C004-E2E-019",  # Wrong prefix
        "acc:maintain-ux:C4-E2E-019",     # WMBT not zero-padded
    ]

    for urn in invalid_urns:
        assert not re.match(URN_PATTERN, urn), f"Should not match: {urn}"


# SPEC-TESTER-CONV-0078: Platform validation enforces filename convention compliance
def test_dart_files_match_convention():
    """Validate Dart test files follow URN-based naming convention."""
    from atdd.tester.utils.filename import parse_acceptance_urn, dart_filename

    # Pattern: {WMBT}_{HARNESS}_{NNN}[_{slug}]_test.dart
    dart_pattern = re.compile(r'^([A-Z][0-9]{3})_([A-Z0-9]+)_([0-9]{3})(?:_([a-z0-9_]+))?_test\.dart$')

    test_dirs = [
        REPO_ROOT / "test",
        REPO_ROOT / "integration_test",
    ]

    violations = []

    for test_dir in test_dirs:
        if not test_dir.exists():
            continue

        for dart_file in test_dir.rglob("*_test.dart"):
            filename = dart_file.name

            # Check pattern compliance
            match = dart_pattern.match(filename)
            if not match:
                # Check if there's a URN comment to determine expected filename
                content = dart_file.read_text()
                urn_match = re.search(r'// urn: (acc:[a-z][a-z0-9-]*:[A-Z][0-9]{3}-[A-Z0-9]+-[0-9]{3}(?:-[a-z0-9-]+)?)', content)

                if urn_match:
                    urn = urn_match.group(1)
                    expected = dart_filename(urn)
                    violations.append({
                        'file': str(dart_file.relative_to(REPO_ROOT)),
                        'actual': filename,
                        'expected': expected,
                        'urn': urn
                    })

    # Allow some violations during migration, but report them
    if violations:
        report = "\n".join([
            f"  {v['file']}: {v['actual']} → {v['expected']} (URN: {v['urn']})"
            for v in violations[:5]  # Show first 5
        ])
        print(f"\nFilename convention violations found:\n{report}")

    # For now, just log violations without failing
    # In the future, this should assert len(violations) == 0
    assert True, "Validation complete (violations logged)"


def test_typescript_files_match_convention():
    """Validate TypeScript test files follow URN-based naming convention."""
    from atdd.tester.utils.filename import typescript_filename

    # Pattern: {wmbt}-{harness}-{nnn}[-{slug}].test.ts
    ts_pattern = re.compile(r'^([a-z][0-9]{3})-([a-z0-9]+)-([0-9]{3})(?:-([a-z0-9-]+))?\.test\.ts$')

    test_dirs = [
        REPO_ROOT / "supabase" / "functions",
        REPO_ROOT / "e2e",
    ]

    violations = []

    for test_dir in test_dirs:
        if not test_dir.exists():
            continue

        for ts_file in test_dir.rglob("*.test.ts"):
            filename = ts_file.name
            match = ts_pattern.match(filename)

            if not match:
                content = ts_file.read_text()
                # V3: // Acceptance: acc:...
                urn_match = re.search(
                    r'//\s*[Aa]cceptance:\s*(acc:[a-z][a-z0-9-]*:[A-Z][0-9]{3}-[A-Z0-9]+-[0-9]{3}(?:-[a-z0-9-]+)?)',
                    content
                )
                # Legacy: // urn: acc:...
                if not urn_match:
                    urn_match = re.search(
                        r'// urn: (acc:[a-z][a-z0-9-]*:[A-Z][0-9]{3}-[A-Z0-9]+-[0-9]{3}(?:-[a-z0-9-]+)?)',
                        content
                    )

                if urn_match:
                    urn = urn_match.group(1)
                    expected = typescript_filename(urn)
                    violations.append({
                        'file': str(ts_file.relative_to(REPO_ROOT)),
                        'actual': filename,
                        'expected': expected,
                        'urn': urn
                    })

    if violations:
        report = "\n".join([
            f"  {v['file']}: {v['actual']} → {v['expected']} (URN: {v['urn']})"
            for v in violations[:5]
        ])
        print(f"\nFilename convention violations found:\n{report}")

    assert True, "Validation complete (violations logged)"


def test_typescript_preact_files_match_convention():
    """Validate Preact TypeScript test files follow URN-based naming convention."""
    from atdd.tester.utils.filename import typescript_preact_filename

    ts_pattern = re.compile(r'^([A-Z][0-9]{3})_([A-Z0-9]+)_([0-9]{3})(?:_([a-z0-9_]+))?\.test\.ts(x)?$')

    test_dirs = [
        REPO_ROOT / "web" / "tests",
    ]

    violations = []

    for test_dir in test_dirs:
        if not test_dir.exists():
            continue

        ts_files = list(test_dir.rglob("*.test.ts")) + list(test_dir.rglob("*.test.tsx"))
        for ts_file in ts_files:
            filename = ts_file.name
            match = ts_pattern.match(filename)

            if not match:
                content = ts_file.read_text()
                # V3: // Acceptance: acc:...
                urn_match = re.search(
                    r'//\s*[Aa]cceptance:\s*(acc:[a-z][a-z0-9-]*:[A-Z][0-9]{3}-[A-Z0-9]+-[0-9]{3}(?:-[a-z0-9-]+)?)',
                    content
                )
                # Legacy: // URN: acc:... or // urn: acc:...
                if not urn_match:
                    urn_match = re.search(
                        r'//\s*(?:urn|URN):\s*(acc:[a-z][a-z0-9-]*:[A-Z][0-9]{3}-[A-Z0-9]+-[0-9]{3}(?:-[a-z0-9-]+)?)',
                        content
                    )

                if urn_match:
                    urn = urn_match.group(1)
                    expected = typescript_preact_filename(urn)
                    violations.append({
                        'file': str(ts_file.relative_to(REPO_ROOT)),
                        'actual': filename,
                        'expected': expected,
                        'urn': urn
                    })

    if violations:
        report = "\n".join([
            f"  {v['file']}: {v['actual']} → {v['expected']} (URN: {v['urn']})"
            for v in violations[:5]
        ])
        print(f"\nFilename convention violations found:\n{report}")

    assert True, "Validation complete (violations logged)"


def test_python_files_match_convention():
    """Validate Python test files follow URN-based naming convention."""
    from atdd.tester.utils.filename import python_filename

    # Pattern: test_{wmbt}_{harness}_{nnn}[_{slug}].py
    py_pattern = re.compile(r'^test_([a-z][0-9]{3})_([a-z0-9]+)_([0-9]{3})(?:_([a-z0-9_]+))?\.py$')

    test_dirs = [
        REPO_ROOT / "tests",
        ATDD_PKG_DIR / "coach" / "validators",
        ATDD_PKG_DIR / "tester" / "validators",
    ]

    violations = []

    for test_dir in test_dirs:
        if not test_dir.exists():
            continue

        for py_file in test_dir.rglob("test_*.py"):
            filename = py_file.name
            match = py_pattern.match(filename)

            if not match:
                try:
                    content = py_file.read_text()
                    urn_match = re.search(r'# urn: (acc:[a-z][a-z0-9-]*:[A-Z][0-9]{3}-[A-Z0-9]+-[0-9]{3}(?:-[a-z0-9-]+)?)', content)

                    if urn_match:
                        urn = urn_match.group(1)
                        expected = python_filename(urn)
                        violations.append({
                            'file': str(py_file.relative_to(REPO_ROOT)),
                            'actual': filename,
                            'expected': expected,
                            'urn': urn
                        })
                except Exception:
                    pass  # Skip files that can't be read

    if violations:
        report = "\n".join([
            f"  {v['file']}: {v['actual']} → {v['expected']} (URN: {v['urn']})"
            for v in violations[:5]
        ])
        print(f"\nFilename convention violations found:\n{report}")

    assert True, "Validation complete (violations logged)"


def test_urn_comment_extraction():
    """Test extraction of URN from test file comments."""
    # Dart style: // urn: acc:...
    dart_content = """
// urn: acc:maintain-ux:C004-E2E-019-user-connection
import 'package:flutter_test/flutter_test.dart';
"""
    urn_match = re.search(r'// urn: (acc:[^\s]+)', dart_content)
    assert urn_match
    assert urn_match.group(1) == "acc:maintain-ux:C004-E2E-019-user-connection"

    # Python style: # urn: acc:...
    python_content = """
# urn: acc:commit-state:D001-UNIT-042
import pytest
"""
    urn_match = re.search(r'# urn: (acc:[^\s]+)', python_content)
    assert urn_match
    assert urn_match.group(1) == "acc:commit-state:D001-UNIT-042"
