import asyncio
import os
import signal
import time
from typing import Any
from quart import Quart, jsonify, request, send_from_directory, Response
from lib.browser_navigator import BrowserNavigator

from hypercorn.config import Config
from hypercorn.asyncio import serve

from lib.page_management import PageState
from lib.plugin_loader import initialize_plugins, get_plugin_registry

# Import routers
from routers.ops import register_ops_routes
from routers.primitive import register_primitive_routes
from routers.system import register_system_routes
from routers.plugin import register_plugin_routes


# Browser profile path - use env var for Docker, or platform-specific default
USER_DATA_DIR = os.getenv('BROWSER_PROFILE')
if not USER_DATA_DIR:
    # Fallback to Windows profile if not in Docker
    if os.name == 'nt':
        USER_DATA_DIR = r"C:\Users\matsca\AppData\Roaming\Mozilla\Firefox\Profiles\aqa6u4xk.default-default"
    else:
        # Linux/WSL fallback
        USER_DATA_DIR = "/tmp/firefox-profile"

# Delay between browser actions in milliseconds.
SLOWMO = float(os.getenv('BROWSER_SLOWMO', 200))
MAX_PAGES = 5  # Maximum number of concurrent pages/tabs

app = Quart(__name__)
browser_navigator = None
shutdown_event = asyncio.Event()

# Helper functions for routers
def get_browser_navigator() -> Any | BrowserNavigator | None:
    """Get the current browser_navigator instance."""
    return browser_navigator

def set_browser_navigator(instance):
    """Set the browser_navigator instance."""
    global browser_navigator
    browser_navigator = instance

# Register all routers immediately after app creation
register_ops_routes("/api/v1", app, get_browser_navigator)
register_primitive_routes("/api/v1", app, get_browser_navigator)
register_system_routes("/api/v1", app, get_browser_navigator, set_browser_navigator, shutdown_event, USER_DATA_DIR, SLOWMO, MAX_PAGES)

print("📡 All routes registered with /api/v1 prefix")
print("⏳ Plugin routes will be registered after plugin discovery...")

async def cleanup_navigator():
    """Cleanup browser navigator resources."""
    global browser_navigator
    if browser_navigator:
        print("🔒 Shutting down browser navigator...")
        try:
            await browser_navigator.close()
            print("✅ Browser navigator closed successfully")
        except Exception as e:
            print(f"⚠️ Error during browser navigator cleanup: {e}")
        browser_navigator = None

def signal_handler(signum, frame):
    """Handle shutdown signals."""
    print(f"\n🛑 Received signal {signum}, initiating graceful shutdown...")
    shutdown_event.set()

# Register signal handlers for graceful shutdown
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

@app.before_serving
async def startup():
    """Initialize the browser navigator and plugins before the server starts."""
    # Initialize plugin system
    print("\n" + "="*60)
    plugin_registry = initialize_plugins("plugins")
    print("="*60 + "\n")
    
    # Register plugin routes after discovery
    register_plugin_routes("/api/v1", app, get_browser_navigator)
    
    # Initialize browser navigator
    global browser_navigator
    browser_navigator = BrowserNavigator(
        user_data_dir=USER_DATA_DIR,
        slowmo=SLOWMO,
        max_pages=MAX_PAGES
    )
    await browser_navigator.initialize()
    print("🚀 Browser navigator initialized and ready")

@app.after_serving
async def shutdown():
    """Clean up the browser navigator when the server shuts down."""
    await cleanup_navigator()

@app.before_request
async def log_request_start():
    """Log every incoming request."""
    request_id = f"req_{int(time.time() * 1000) % 10000}"
    print(f"🌐 [{request_id}] INCOMING REQUEST: {request.method} {request.path}")
    # Store request_id in g for use in other handlers
    from quart import g
    g.request_id = request_id

@app.after_request
async def log_request_end(response):
    """Log request completion and add CORS headers."""
    from quart import g
    request_id = getattr(g, 'request_id', 'unknown')
    print(f"🌐 [{request_id}] REQUEST COMPLETED: {response.status_code}")
    
    # Add CORS headers to allow requests from the same origin
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
    response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
    
    return response

@app.route("/")
async def home():
    """Serve the browser control panel HTML interface."""
    try:
        import os
        current_dir = os.path.dirname(os.path.abspath(__file__))
        html_path = os.path.join(current_dir, 'html', 'browser_control.html')
        
        with open(html_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # Set proper content type for HTML
        from quart import Response
        return Response(content, mimetype='text/html')
        
    except FileNotFoundError:
        return """
        <h1>Browser Control Panel Not Found</h1>
        <p>The browser_control.html file is missing. Please ensure it exists in the html directory.</p>
        <p><a href="/doc/api">View API Documentation</a></p>
        """

@app.route("/doc/api")
async def api_docs():
    """API documentation and welcome message."""
    try:
        import os
        current_dir = os.path.dirname(os.path.abspath(__file__))
        html_path = os.path.join(current_dir, 'html', 'api_docs.html')
        
        with open(html_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # Set proper content type for HTML
        from quart import Response
        return Response(content, mimetype='text/html')
        
    except FileNotFoundError:
        return """
        <h1>API Documentation Not Found</h1>
        <p>The api_docs.html file is missing. Please ensure it exists in the html directory.</p>
        <p><a href="/">← Back to Control Panel</a></p>
        """

@app.route("/html/<filename>")
async def serve_html(filename):
    """Serve HTML and CSS files from the html directory."""
    try:
        return await send_from_directory('html', filename)
    except FileNotFoundError:
        return jsonify({"error": f"File '{filename}' not found"}), 404

@app.route("/<filename>.css")
async def serve_css(filename):
    """Serve CSS files from the html directory with proper content type."""
    try:
        from quart import Response
        import os
        
        current_dir = os.path.dirname(os.path.abspath(__file__))
        css_path = os.path.join(current_dir, 'html', f'{filename}.css')
        
        with open(css_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        return Response(content, mimetype='text/css')
    except FileNotFoundError:
        return jsonify({"error": f"CSS file '{filename}.css' not found"}), 404


# Note: All API routes (/tools, /ops, /primitive, /system) are registered via routers
# See routers/*.py for route definitions

async def main():
    """Main async function with proper cleanup."""
    try:

        
        config = Config()
        config.bind = ["0.0.0.0:5000"]
        
        print(f"🚀 Starting server with {config.workers} workers")
        
        # Create server task
        server_task = asyncio.create_task(serve(app, config))
        
        # Wait for shutdown signal or server completion
        done, pending = await asyncio.wait(
            [server_task, asyncio.create_task(shutdown_event.wait())],
            return_when=asyncio.FIRST_COMPLETED
        )
        
        # Cancel remaining tasks
        for task in pending:
            task.cancel()
            try:
                await task
            except asyncio.CancelledError:
                pass
        
    except KeyboardInterrupt:
        print("\n🛑 Keyboard interrupt received")
    finally:
        # Ensure cleanup happens
        await cleanup_navigator()
        print("🎉 Cleanup completed")

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n👋 Goodbye!")



