#!/usr/bin/env python3
"""
Script to apply monitoring and caching decorators to all tool modules.

This script applies DRY patterns by automatically adding performance monitoring
and caching to all tool functions across the codebase.
"""
# flake8: noqa: E226

import os
import re
from pathlib import Path


def add_imports_to_file(file_path: Path) -> bool:
    """Add monitoring and cache imports to a tool file."""
    with open(file_path, "r") as f:
        content = f.read()

    # Check if imports already exist
    if "from ..monitoring import performance_monitor" in content:
        print(f"✅ {file_path.name}: Imports already exist")
        return False

    # Find the import section and add our imports
    import_pattern = r"(from \.\.database import.*?\n)(from \.\.media import.*?\n)"

    def replace_imports(match):
        return (
            match.group(1)
            + "from ..cache import cache_by_site_and_language\n"
            + match.group(2)
            + "from ..monitoring import performance_monitor\n"
        )

    new_content = re.sub(import_pattern, replace_imports, content)

    if new_content != content:
        with open(file_path, "w") as f:
            f.write(new_content)
        print(f"✅ {file_path.name}: Added imports")
        return True
    else:
        print(f"⚠️  {file_path.name}: Could not add imports (pattern not found)")
        return False


def add_decorators_to_functions(file_path: Path) -> bool:
    """Add decorators to all functions in a tool file."""
    with open(file_path, "r") as f:
        content = f.read()

    # Check if decorators already exist
    if "@performance_monitor" in content:
        print(f"✅ {file_path.name}: Decorators already exist")
        return False

    # Extract module name for tool naming
    module_name = file_path.stem  # e.g., 'activities' from 'activities.py'

    # Pattern to match function definitions
    function_patterns = [
        (rf"def list_{module_name}\(", f"list_{module_name}", 300),  # 5 minutes
        (
            rf"def get_{module_name[:-1]}_details\(",
            f"get_{module_name[:-1]}_details",
            600,
        ),  # 10 minutes
        (rf"def search_{module_name}\(", f"search_{module_name}", 180),  # 3 minutes
    ]

    # Special cases for different naming patterns
    if module_name == "menu":
        function_patterns = [
            (r"def list_menu_items\(", "list_menu_items", 300),
            (r"def get_menu_item_details\(", "get_menu_item_details", 600),
            (r"def search_menu_items\(", "search_menu_items", 180),
        ]
    elif module_name == "galleries":
        function_patterns = [
            (r"def list_galleries\(", "list_galleries", 300),
            (r"def get_gallery_details\(", "get_gallery_details", 600),
            (r"def search_galleries\(", "search_galleries", 180),
        ]

    modified = False

    for pattern, tool_name, ttl in function_patterns:
        # Find function definition
        func_match = re.search(pattern, content)
        if func_match:
            # Find the start of the function (including any existing decorators)
            func_start = func_match.start()

            # Look backwards to find the actual start (before any decorators)
            lines = content[:func_start].split("\n")

            # Find the line where we should insert decorators
            insert_line = len(lines) - 1
            while insert_line > 0 and (
                lines[insert_line].strip() == ""
                or lines[insert_line].strip().startswith("@")
            ):
                insert_line -= 1

            # Insert decorators
            decorators = [
                f'@performance_monitor("{tool_name}")',
                f"@cache_by_site_and_language(ttl={ttl})  # Cache for {ttl // 60} minutes",
            ]

            # Insert decorators before the function
            lines.insert(insert_line + 1, "")
            for i, decorator in enumerate(decorators):
                lines.insert(insert_line + 2 + i, decorator)

            content = "\n".join(lines)
            modified = True
            print(f"✅ {file_path.name}: Added decorators to {tool_name}")

    if modified:
        with open(file_path, "w") as f:
            f.write(content)
        return True
    else:
        print(f"⚠️  {file_path.name}: No functions found to decorate")
        return False


def process_tool_files():
    """Process all tool files in the src/tools directory."""
    tools_dir = Path("src/tools")

    if not tools_dir.exists():
        print("❌ src/tools directory not found")
        return

    # Get all Python files except __init__.py
    tool_files = [f for f in tools_dir.glob("*.py") if f.name != "__init__.py"]

    print(f"🔧 Processing {len(tool_files)} tool files...")
    print("=" * 50)

    for tool_file in tool_files:
        print(f"\n📁 Processing {tool_file.name}:")

        # Add imports
        imports_added = add_imports_to_file(tool_file)

        # Add decorators
        decorators_added = add_decorators_to_functions(tool_file)

        if imports_added or decorators_added:
            print(f"✅ {tool_file.name}: Successfully updated")
        else:
            print(f"ℹ️  {tool_file.name}: No changes needed")


def main():
    """Main function."""
    print("🏨 Hotel MCP - Applying Monitoring and Caching")
    print("=" * 50)
    print("This script will add performance monitoring and caching")
    print("decorators to all tool functions using DRY patterns.")
    print()

    # Change to project root
    script_dir = Path(__file__).parent
    project_root = script_dir.parent
    os.chdir(project_root)

    print(f"📂 Working directory: {os.getcwd()}")
    print()

    # Process tool files
    process_tool_files()

    print("\n" + "=" * 50)
    print("🎉 Monitoring and caching application completed!")
    print()
    print("Next steps:")
    print("1. Run tests to ensure everything works: uv run pytest")
    print("2. Check monitoring: Use get_monitoring_summary() tool")
    print("3. Check cache: Use get_cache_summary() tool")


if __name__ == "__main__":
    main()
