"""Browser service using Playwright for web automation.

This service provides a local browser that can be controlled through the tunnel.
The browser can run in visible (headed) or hidden (headless) mode.
"""

import asyncio
import logging
import socket
from typing import Optional, Any

logger = logging.getLogger(__name__)


class BrowserService:
    """Manages a local Playwright browser instance."""
    
    def __init__(self, headless: bool = False, port: int = 9223):
        self.headless = headless
        self.port = port
        self.playwright: Optional[Any] = None
        self.browser: Optional[Any] = None
        self.running = False
    
    def _is_port_open(self, port: int, host: str = 'localhost') -> bool:
        """Check if a port is open (browser is listening)."""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(0.5)
            result = sock.connect_ex((host, port))
            sock.close()
            return result == 0
        except Exception:
            return False
    
    async def _check_browser_alive(self) -> bool:
        """Check if the browser is actually running."""
        if not self.browser:
            return False
        
        try:
            # Check if browser process is connected
            if not self.browser.is_connected():
                logger.warning("Browser process disconnected")
                return False
            
            # Also check if CDP port is listening
            if not self._is_port_open(self.port):
                logger.warning(f"CDP port {self.port} not responding")
                return False
            
            return True
        except Exception as e:
            logger.warning(f"Browser health check failed: {e}")
            return False
        
    async def start(self):
        """Start the browser service."""
        # Check if supposedly running browser is actually alive
        if self.running:
            is_alive = await self._check_browser_alive()
            if is_alive:
                logger.warning("Browser service already running")
                return
            else:
                logger.warning("Browser marked as running but not responding - cleaning up")
                await self.cleanup()
        
        try:
            # Import playwright dynamically (optional dependency)
            from playwright.async_api import async_playwright  # type: ignore
            
            logger.info(f"Starting browser service (headless={self.headless}, port={self.port})")
            
            # Start Playwright
            self.playwright = await async_playwright().start()
            
            # Launch Chrome (stable) with CDP enabled
            # Using 'chrome' channel for better stability than bundled Chromium
            self.browser = await self.playwright.chromium.launch(channel="chrome", 
                headless=self.headless,
                args=[
                    f'--remote-debugging-port={self.port}',
                    '--disable-blink-features=AutomationControlled',
                    '--no-sandbox'
                ]
            )
            
            self.running = True
            logger.info(f"✅ Browser service started on localhost:{self.port}")
            
            if not self.headless:
                logger.info("Browser window is visible on your screen")
            
        except ImportError:
            logger.error("Playwright not installed. Install with: pip install mcpbundles[browser]")
            raise
        except Exception as e:
            logger.error(f"Failed to start browser service: {e}")
            await self.cleanup()
            raise
    
    async def stop(self):
        """Stop the browser service."""
        if not self.running:
            logger.warning("Browser service not running")
            return
        
        logger.info("Stopping browser service...")
        await self.cleanup()
        logger.info("✅ Browser service stopped")
    
    async def cleanup(self):
        """Clean up browser resources."""
        self.running = False
        
        if self.browser:
            try:
                await self.browser.close()
            except Exception as e:
                logger.error(f"Error closing browser: {e}")
            self.browser = None
        
        if self.playwright:
            try:
                await self.playwright.stop()
            except Exception as e:
                logger.error(f"Error stopping playwright: {e}")
            self.playwright = None
    
    async def update_config(self, headless: bool):
        """Update browser configuration.
        
        If headless mode changes, restart the browser.
        """
        if self.headless == headless:
            logger.info("Browser config unchanged")
            return
        
        logger.info(f"Updating browser config: headless={headless}")
        self.headless = headless
        
        if self.running:
            logger.info("Restarting browser with new config...")
            await self.stop()
            await self.start()
    
    def get_status(self) -> dict:
        """Get current browser service status."""
        return {
            "enabled": self.running,
            "headless": self.headless,
            "port": self.port,
            "mode": "hidden" if self.headless else "visible"
        }
    
    async def get_status_checked(self) -> dict:
        """Get current browser service status with health check."""
        if self.running:
            is_alive = await self._check_browser_alive()
            if not is_alive:
                logger.warning("Browser was marked running but health check failed - cleaning up")
                await self.cleanup()
        
        return self.get_status()
