#!/usr/bin/env python3
"""
REAL Gemini Deep Think - CDP Approach (Windows Python)
Strategy: Close Chrome, relaunch with --remote-debugging-port, connect via CDP

This enables:
1. Real Chrome with the user's actual session
2. Thinking/Pro mode if user has Gemini Advanced subscription
3. True Deep Think capability

Run from Windows Python:
python E:\genesis-system\scripts\deep_think_cdp.py
"""

import os
import sys
import time
import json
import subprocess
import socket
from datetime import datetime

# Windows paths
CHROME_EXE = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
CHROME_USER_DATA = r"C:\Users\P3\AppData\Local\Google\Chrome\User Data"
SCREENSHOTS_DIR = r"E:\genesis-system\deep_think_results\screenshots"
RESULTS_DIR = r"E:\genesis-system\deep_think_results"
CDP_PORT = 9222

os.makedirs(SCREENSHOTS_DIR, exist_ok=True)

step_log = []
workflow_steps = []

def log(msg, level="INFO"):
    ts = datetime.now().strftime("%H:%M:%S")
    line = f"[{ts}] [{level}] {msg}"
    print(line, flush=True)
    step_log.append(line)

def screenshot(page, name):
    path = os.path.join(SCREENSHOTS_DIR, f"{name}.png")
    try:
        page.screenshot(path=path, full_page=False)
        log(f"Screenshot: {name}")
    except Exception as e:
        log(f"Screenshot failed '{name}': {e}", "WARN")
    return path

def is_port_open(host, port, timeout=2):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        result = sock.connect_ex((host, port))
        sock.close()
        return result == 0
    except:
        return False

def kill_chrome():
    """Kill all Chrome processes"""
    log("Killing existing Chrome processes...")
    result = subprocess.run(
        ["taskkill", "/F", "/IM", "chrome.exe", "/T"],
        capture_output=True, text=True
    )
    log(f"Kill result: {result.stdout.strip()} {result.stderr.strip()}")
    time.sleep(3)

def launch_chrome_with_debug():
    """Launch Chrome with remote debugging enabled"""
    log(f"Launching Chrome with remote debugging on port {CDP_PORT}...")
    cmd = [
        CHROME_EXE,
        f"--remote-debugging-port={CDP_PORT}",
        f"--user-data-dir={CHROME_USER_DATA}",
        "--profile-directory=Default",
        "--no-first-run",
        "--no-default-browser-check",
        "--disable-background-mode",
        "about:blank"
    ]

    proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    log(f"Chrome process launched: PID={proc.pid}")

    # Wait for CDP port to open
    for i in range(20):
        time.sleep(1)
        if is_port_open("localhost", CDP_PORT):
            log(f"[OK] CDP port {CDP_PORT} is open after {i+1}s")
            return proc
        log(f"  Waiting for port... {i+1}s")

    log(f"[ERROR] CDP port {CDP_PORT} did not open after 20s", "ERROR")
    return proc


def run():
    from playwright.sync_api import sync_playwright

    log("=" * 60)
    log("GEMINI DEEP THINK - CDP APPROACH")
    log(f"Started: {datetime.now().isoformat()}")
    log("=" * 60)

    TEST_PROMPT = "What is the single most important strategic decision for a new AI voice widget product targeting Australian digital agencies in 2026?"

    result = {
        "status": "unknown",
        "logged_in": False,
        "mode_selected": None,
        "deep_think_found": False,
        "deep_think_modes": {},
        "response_text": "",
        "workflow_steps": [],
        "screenshots": [],
        "errors": [],
    }

    chrome_proc = None

    try:
        # Step 1: Kill existing Chrome and relaunch with debug port
        log("\n[STEP 1] Preparing Chrome with remote debugging...")
        kill_chrome()
        chrome_proc = launch_chrome_with_debug()

        if not is_port_open("localhost", CDP_PORT):
            log("[ERROR] CDP port not available!", "ERROR")
            result["status"] = "error"
            result["errors"].append("CDP port not available")
            return result

        workflow_steps.append({
            "step": 1,
            "action": "Launch Chrome with CDP",
            "command": f'"{CHROME_EXE}" --remote-debugging-port={CDP_PORT} --user-data-dir="{CHROME_USER_DATA}"',
            "note": "Kill existing Chrome first, then launch fresh with debug port"
        })

    except Exception as e:
        log(f"[ERROR] Chrome setup failed: {e}", "ERROR")
        result["errors"].append(f"Chrome setup: {e}")
        # Fall through to try CDP connection anyway

    with sync_playwright() as p:
        browser = None
        page = None

        try:
            # Connect to Chrome via CDP
            log(f"\n[STEP 2] Connecting to Chrome via CDP (ws://localhost:{CDP_PORT})...")
            browser = p.chromium.connect_over_cdp(f"http://localhost:{CDP_PORT}")
            log(f"[OK] Connected to Chrome via CDP!")
            log(f"Browser version: {browser.version}")

            workflow_steps.append({
                "step": 2,
                "action": "Connect via CDP",
                "code": f'browser = p.chromium.connect_over_cdp("http://localhost:{CDP_PORT}")',
            })

            # Get existing page or create new
            if browser.contexts:
                ctx = browser.contexts[0]
                if ctx.pages:
                    page = ctx.pages[0]
                    log(f"Using existing page: {page.url}")
                else:
                    page = ctx.new_page()
            else:
                page = browser.new_page()

            # Set viewport
            try:
                page.set_viewport_size({"width": 1440, "height": 900})
            except:
                pass

            # Navigate to Gemini
            log("\n[STEP 3] Navigating to gemini.google.com...")
            page.goto("https://gemini.google.com", timeout=45000, wait_until="domcontentloaded")
            time.sleep(6)
            screenshot(page, "CDP_01_loaded")

            log(f"URL: {page.url}")
            log(f"Title: {page.title()}")

            # Check login state
            log("\n[STEP 4] Checking login state...")
            elements = page.evaluate("""
                () => {
                    return Array.from(document.querySelectorAll(
                        'button, [role="button"], a, [aria-label]'
                    ))
                    .filter(el => {
                        const r = el.getBoundingClientRect();
                        return r.width > 0 && r.height > 0;
                    })
                    .map(el => ({
                        tag: el.tagName,
                        text: el.textContent?.trim()?.substring(0, 60) || '',
                        aria: el.getAttribute('aria-label') || '',
                    }));
                }
            """)

            log(f"Visible elements count: {len(elements)}")
            for el in elements:
                if el.get('text') or el.get('aria'):
                    log(f"  [{el['tag']}] '{el.get('text','')}' / '{el.get('aria','')}'")

            has_signin = any('sign in' in (el.get('text') or '').lower() for el in elements)
            has_account = any(
                any(x in (el.get('aria') or '').lower()
                    for x in ['google account', 'my account', 'profile'])
                for el in elements
            )

            # Look for profile picture
            has_profile_img = page.evaluate("""
                () => {
                    const imgs = document.querySelectorAll('img[alt*="profile"], img[class*="avatar"], img[class*="profile"]');
                    return imgs.length > 0;
                }
            """)

            log(f"Sign in button: {has_signin}")
            log(f"Account element: {has_account}")
            log(f"Profile image: {has_profile_img}")

            is_logged_in = has_account or has_profile_img or not has_signin
            result["logged_in"] = is_logged_in
            log(f"LOGIN STATE: {'LOGGED IN' if is_logged_in else 'NOT LOGGED IN'}")
            screenshot(page, "CDP_02_login_check")

            # Check mode picker
            log("\n[STEP 5] Checking mode picker (Deep Think availability)...")
            mode_picker = page.locator('[aria-label="Open mode picker"]')

            if mode_picker.count() > 0:
                log(f"Mode picker text: '{mode_picker.text_content()}'")
                mode_picker.click()
                time.sleep(2)
                screenshot(page, "CDP_03_mode_dropdown")

                # Get all mode options
                mode_options = page.evaluate("""
                    () => {
                        const els = document.querySelectorAll('[role="menuitemradio"], [data-mode-id]');
                        return Array.from(els).map(el => ({
                            text: el.textContent?.trim()?.substring(0, 100),
                            aria: el.getAttribute('aria-label'),
                            disabled: el.getAttribute('aria-disabled'),
                            checked: el.getAttribute('aria-checked'),
                            'data-mode-id': el.getAttribute('data-mode-id'),
                            'data-test-id': el.getAttribute('data-test-id'),
                            x: Math.round(el.getBoundingClientRect().x),
                            y: Math.round(el.getBoundingClientRect().y),
                        }));
                    }
                """)

                log(f"\nMode options found: {len(mode_options)}")
                for opt in mode_options:
                    status = "AVAILABLE" if opt.get('disabled') != 'true' else "LOCKED"
                    log(f"  [{status}] '{opt.get('text','')}' id={opt.get('data-mode-id','')}")

                result["deep_think_modes"] = {
                    opt.get('data-test-id', opt.get('text', 'unknown')): {
                        "text": opt.get('text'),
                        "available": opt.get('disabled') != 'true',
                        "mode_id": opt.get('data-mode-id'),
                    }
                    for opt in mode_options
                }

                # Try to select Pro or Thinking mode if available
                available = [opt for opt in mode_options if opt.get('disabled') != 'true']
                thinking_available = [opt for opt in mode_options
                                      if opt.get('disabled') != 'true' and
                                      any(x in (opt.get('text') or '').lower()
                                          for x in ['thinking', 'pro', 'deep'])]

                if thinking_available:
                    target = thinking_available[0]
                    log(f"[OK] Selecting thinking mode: '{target.get('text')}'")
                    page.mouse.click(target['x'] + 30, target['y'] + 10)
                    time.sleep(2)
                    screenshot(page, "CDP_04_deep_think_selected")
                    result["mode_selected"] = target.get('text', 'Thinking')
                    result["deep_think_found"] = True

                    workflow_steps.append({
                        "step": 5,
                        "action": "Select Deep Think mode",
                        "mode": target.get('text'),
                        "selector": f'[data-test-id="{target.get("data-test-id")}"]',
                        "code": f'page.locator(\'[data-test-id="{target.get("data-test-id")}"]\').click()',
                        "note": "Only available with Gemini Advanced/subscription"
                    })
                else:
                    log("[INFO] Thinking/Pro modes locked - subscription required")
                    log("[INFO] Using Fast mode as fallback")
                    page.keyboard.press("Escape")
                    result["mode_selected"] = "Fast (subscription required for Thinking/Pro)"

                    # Capture subscription gate info
                    result["subscription_gate"] = {
                        "message": "Thinking and Pro modes require Gemini Advanced subscription",
                        "modes_visible": [opt.get('text') for opt in mode_options],
                        "modes_available": [opt.get('text') for opt in available],
                        "modes_locked": [opt.get('text') for opt in mode_options if opt.get('disabled') == 'true'],
                    }

            time.sleep(1)
            screenshot(page, "CDP_05_mode_confirmed")

            # Enter prompt
            log(f"\n[STEP 6] Entering prompt...")
            input_el = page.locator('[aria-label="Enter a prompt for Gemini"]').first
            if input_el.count() == 0:
                input_el = page.locator('div[contenteditable="true"]').first

            if input_el.count() > 0 and input_el.is_visible():
                input_el.click()
                time.sleep(0.3)
                page.keyboard.type(TEST_PROMPT, delay=15)
                time.sleep(1)
                screenshot(page, "CDP_06_prompt")

                workflow_steps.append({
                    "step": 6,
                    "action": "Enter prompt",
                    "selector": '[aria-label="Enter a prompt for Gemini"]',
                    "code": 'page.locator(\'[aria-label="Enter a prompt for Gemini"]\').click(); page.keyboard.type(prompt)',
                })

                # Submit
                send_btn = page.locator('[aria-label="Send message"]')
                if send_btn.count() > 0:
                    send_btn.click()
                else:
                    page.keyboard.press("Enter")

                workflow_steps.append({
                    "step": 7,
                    "action": "Submit",
                    "code": 'page.locator(\'[aria-label="Send message"]\').click()',
                })

                time.sleep(5)
                screenshot(page, "CDP_07_submitted")
                log("Prompt submitted!")

                # Wait for response
                log(f"\n[STEP 7] Waiting for response...")
                prev_len = 0
                stable = 0
                full_response = ""

                for i in range(80):  # 80 x 2s = 160s
                    time.sleep(2)
                    elapsed = (i+1)*2

                    # Extract response
                    curr = page.evaluate("""
                        () => {
                            const responses = document.querySelectorAll('model-response');
                            if (responses.length > 0) {
                                return Array.from(responses)
                                    .map(r => r.innerText || '')
                                    .join('\\n---\\n');
                            }
                            return '';
                        }
                    """) or ""

                    is_gen = page.evaluate("""
                        () => !!document.querySelector(
                            '[aria-busy="true"], .generating, [class*="loading"]:not([class*="complete"])'
                        )
                    """)

                    if len(curr) == prev_len:
                        stable += 1
                    else:
                        stable = 0
                        prev_len = len(curr)
                        full_response = curr

                    if elapsed % 15 == 0:
                        log(f"  {elapsed}s: len={len(curr)}, generating={is_gen}, stable={stable}")
                        screenshot(page, f"CDP_08_wait_{elapsed:03d}s")

                    if stable >= 4 and not is_gen and elapsed > 15 and len(curr) > 200:
                        log(f"[OK] Response complete at {elapsed}s ({len(curr)} chars)")
                        full_response = curr
                        break

                screenshot(page, "CDP_09_final_response")
                result["response_text"] = full_response
                result["status"] = "success" if len(full_response) > 100 else "partial"
                log(f"Response length: {len(full_response)} chars")
                log(f"Preview: {full_response[:400]}")

            else:
                log("[ERROR] Input not found!", "ERROR")
                result["status"] = "no_input"

        except Exception as e:
            log(f"[ERROR] {e}", "ERROR")
            import traceback
            traceback.print_exc()
            result["errors"].append(str(e))
            result["status"] = "error"
            try:
                screenshot(page, "CDP_ERROR")
            except:
                pass

        finally:
            if browser:
                try:
                    browser.close()
                except:
                    pass

    # Clean up Chrome
    if chrome_proc:
        try:
            chrome_proc.terminate()
        except:
            pass

    # Save results
    result["workflow_steps"] = workflow_steps
    result["step_log"] = step_log
    result["screenshots"] = sorted(os.listdir(SCREENSHOTS_DIR))

    with open(os.path.join(RESULTS_DIR, "cdp_results.json"), 'w') as f:
        json.dump(result, f, indent=2, default=str)

    log(f"\nResults saved to: {os.path.join(RESULTS_DIR, 'cdp_results.json')}")
    return result


if __name__ == "__main__":
    result = run()
    print(f"\n{'='*60}")
    print(f"STATUS: {result.get('status')}")
    print(f"LOGGED IN: {result.get('logged_in')}")
    print(f"MODE: {result.get('mode_selected')}")
    print(f"DEEP THINK: {result.get('deep_think_found')}")
    print(f"SUBSCRIPTION GATE: {json.dumps(result.get('subscription_gate', {}), indent=2)}")
    if result.get('response_text'):
        print(f"\nFULL RESPONSE:\n{result['response_text'][:3000]}")
