#!/usr/bin/env python3
"""Script to generate a custom .coveragerc file for backend testing.

This script:
1. Reads SIDEBAR_BUNDLES from frontend styleUtils.ts to get bundled component names
2. Scans backend components for files containing 'legacy = True'
3. Generates a .coveragerc file that omits these paths from coverage reporting

Usage:
    python scripts/generate_coverage_config.py
"""

import re
from pathlib import Path


def extract_sidebar_bundles(frontend_path: Path) -> set[str]:
    """Extract component names from SIDEBAR_BUNDLES in styleUtils.ts."""
    style_utils_path = frontend_path / "src/utils/styleUtils.ts"

    if not style_utils_path.exists():
        print(f"Warning: styleUtils.ts not found at {style_utils_path}")
        return set()

    bundle_names = set()

    with style_utils_path.open(encoding="utf-8") as f:
        content = f.read()

    # Find SIDEBAR_BUNDLES array
    sidebar_match = re.search(r"export const SIDEBAR_BUNDLES = \[(.*?)\];", content, re.DOTALL)
    if not sidebar_match:
        print("Warning: SIDEBAR_BUNDLES not found in styleUtils.ts")
        return set()

    bundles_content = sidebar_match.group(1)

    # Extract name fields using regex
    name_matches = re.findall(r'name:\s*["\']([^"\']+)["\']', bundles_content)

    for name in name_matches:
        bundle_names.add(name)

    print(f"Found {len(bundle_names)} bundled components from SIDEBAR_BUNDLES")
    return bundle_names


def find_legacy_components(backend_components_path: Path) -> set[str]:
    """Find Python files containing 'legacy = True'."""
    legacy_files = set()

    if not backend_components_path.exists():
        print(f"Warning: Backend components path not found: {backend_components_path}")
        return set()

    # Walk through all Python files in components directory
    for py_file in backend_components_path.rglob("*.py"):
        try:
            with py_file.open(encoding="utf-8") as f:
                content = f.read()

            # Check if file contains 'legacy = True'
            if re.search(r"\blegacy\s*=\s*True\b", content):
                # Get relative path from components directory
                rel_path = py_file.relative_to(backend_components_path)
                legacy_files.add(str(rel_path))

        except (UnicodeDecodeError, PermissionError) as e:
            print(f"Warning: Could not read {py_file}: {e}")
            continue

    print(f"Found {len(legacy_files)} legacy component files")
    return legacy_files


def generate_coveragerc(bundle_names: set[str], legacy_files: set[str], output_path: Path):
    """Generate .coveragerc file with omit patterns."""
    # Base coveragerc content
    config_content = """# Auto-generated .coveragerc file
# Generated by scripts/generate_coverage_config.py
# Do not edit manually - changes will be overwritten

[run]
source = src/backend/base/langflow
omit =
    # Test files
    */tests/*
    */test_*
    */*test*

    # Migration files
    */alembic/*
    */migrations/*

    # Cache and build files
    */__pycache__/*
    */.*

    # Init files (typically just imports)
    */__init__.py

    # Deactivate Components
    */components/deactivated/*

"""

    # Add bundled components to omit list
    if bundle_names:
        config_content += "    # Bundled components from SIDEBAR_BUNDLES\n"
        for bundle_name in sorted(bundle_names):
            config_content += f"    */components/{bundle_name}/*\n"
        config_content += "\n"

    # Add legacy components to omit list
    if legacy_files:
        config_content += "    # Legacy components (contain 'legacy = True')\n"
        for legacy_file in sorted(legacy_files):
            # Convert relative path to omit pattern
            omit_pattern = f"    */components/{legacy_file}\n"
            config_content += omit_pattern

    config_content += """
# Note: [report] and [html] sections omitted for Codecov compatibility
# Codecov handles its own reporting and ignores these sections
"""

    # Write the config file
    output_path.parent.mkdir(parents=True, exist_ok=True)
    with output_path.open("w", encoding="utf-8") as f:
        f.write(config_content)

    print(f"Generated .coveragerc at {output_path}")
    print(f"  - Omitting {len(bundle_names)} bundled component directories")
    print(f"  - Omitting {len(legacy_files)} legacy component files")


def main():
    """Main function."""
    # Determine project root (script is in scripts/ directory)
    script_dir = Path(__file__).parent
    project_root = script_dir.parent

    # Paths
    frontend_path = project_root / "src" / "frontend"
    backend_components_path = project_root / "src" / "backend" / "base" / "langflow" / "components"
    output_path = project_root / "src" / "backend" / ".coveragerc"

    print(f"Project root: {project_root}")
    print(f"Frontend path: {frontend_path}")
    print(f"Backend components path: {backend_components_path}")
    print(f"Output path: {output_path}")
    print()

    # Extract bundled component names
    bundle_names = extract_sidebar_bundles(frontend_path)

    # Find legacy components
    legacy_files = find_legacy_components(backend_components_path)

    # Generate .coveragerc file
    generate_coveragerc(bundle_names, legacy_files, output_path)

    print("\nDone! You can now run backend tests with coverage using:")
    print("cd src/backend && python -m pytest --cov=src/backend/base/langflow --cov-config=.coveragerc")


if __name__ == "__main__":
    main()
