"""
Genesis Superior Browser (GSB) — Stealth Engine (Layer 1)
========================================================
Advanced Playwright wrapper designed to bypass enterprise bot detection
without requiring 'Chrome for Testing'.
"""

import asyncio
import logging
import random
from typing import Any, Dict, Optional
from playwright.async_api import async_playwright, Page, BrowserContext

logger = logging.getLogger("genesis_v2.core.browser.stealth")

class StealthEngine:
    def __init__(self, headless: bool = True):
        self.headless = headless
        self.browser = None
        self.context = None
        self.playwright = None

    async def _get_stealth_script(self) -> str:
        """Returns JavaScript to override common bot-detection properties."""
        return """
            // 1. Hide navigator.webdriver
            Object.defineProperty(navigator, 'webdriver', {get: () => undefined});

            // 2. Mock plugins for human-like profile
            Object.defineProperty(navigator, 'plugins', {
                get: () => [
                    { name: 'PDF Viewer', filename: 'internal-pdf-viewer' },
                    { name: 'Chrome PDF Viewer', filename: 'internal-pdf-viewer' }
                ]
            });

            // 3. Realistic screen resolution fallback
            if (!window.screen.width) {
                Object.defineProperty(window.screen, 'width', {get: () => 1920});
                Object.defineProperty(window.screen, 'height', {get: () => 1080});
            }

            // 4. Mock chrome.runtime to look like real Chrome
            window.chrome = {
                runtime: {},
                app: {},
                csi: () => {},
                loadTimes: () => {}
            };

            // 5. Normalizing languages
            Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
        """

    async def launch(self, proxy: Optional[Dict] = None):
        """Launches the stealthy browser instance."""
        self.playwright = await async_playwright().start()
        
        launch_args = [
            "--no-sandbox",
            "--disable-setuid-sandbox",
            "--disable-blink-features=AutomationControlled",
            "--disable-infobars",
            "--window-position=0,0",
            "--ignore-certifcate-errors",
            "--ignore-certifcate-errors-spki-list",
        ]

        # Use MS Edge if available on Windows, else default to chromium
        try:
            self.browser = await self.playwright.chromium.launch(
                headless=self.headless,
                args=launch_args,
                # We avoid using 'chrome-testing' by specifically NOT setting executable_path 
                # unless we have a real browser path.
                proxy=proxy
            )
        except Exception as e:
            logger.error(f"Failed to launch chromium: {e}")
            raise

        self.context = await self.browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
            viewport={"width": 1920, "height": 1080},
            color_scheme="light",
            device_scale_factor=1.0,
            has_touch=False
        )

        # Inject the stealth scripts immediately upon page creation
        await self.context.add_init_script(await self._get_stealth_script())
        logger.info("GSB Stealth Context initialized.")

    async def get_page(self) -> Page:
        if not self.context:
            await self.launch()
        return await self.context.new_page()

    async def human_click(self, page: Page, selector: str):
        """Simulate human-like behavior before clicking."""
        element = await page.wait_for_selector(selector)
        if element:
            box = await element.bounding_box()
            if box:
                # Add jitter to the center point
                x = box["x"] + box["width"] / 2 + random.uniform(-5, 5)
                y = box["y"] + box["height"] / 2 + random.uniform(-2, 2)
                
                # Move mouse in curves (Wait for better implementation of Bezier)
                await page.mouse.move(x, y, steps=10)
                await asyncio.sleep(random.uniform(0.1, 0.4))
                await page.mouse.click(x, y)
                logger.debug(f"Human click on {selector} at ({x}, {y})")

    async def human_type(self, page: Page, selector: str, text: str):
        """Type character-by-character with randomized delays."""
        await page.click(selector)
        for char in text:
            await page.keyboard.press(char)
            # 50ms to 150ms delay per character
            await asyncio.sleep(random.uniform(0.05, 0.15))

    async def close(self):
        if self.context:
            await self.context.close()
        if self.browser:
            await self.browser.close()
        if self.playwright:
            await self.playwright.stop()
        logger.info("GSB Stealth Engine shut down.")
