#!/usr/bin/env python3
"""
FINAL Gemini Deep Think Automation - Windows Native via CDP
Chrome is already running with remote debugging on port 9222.

Run via: python E:\genesis-system\scripts\deep_think_final.py

Prerequisites:
1. Chrome running with --remote-debugging-port=9222 (via launch script or manually)
2. User logged into Gemini in Chrome
3. Gemini Advanced subscription for Thinking/Pro modes (optional - will use Fast if not available)
"""

import os
import sys
import time
import json
from datetime import datetime

# Windows paths
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 run():
    from playwright.sync_api import sync_playwright

    log("=" * 60)
    log("GEMINI DEEP THINK FINAL - CDP TO REAL CHROME")
    log(f"Started: {datetime.now().isoformat()}")
    log(f"CDP: http://localhost:{CDP_PORT}")
    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": {},
        "subscription_gate": None,
        "response_text": "",
        "workflow_steps": [],
        "screenshots": [],
        "errors": [],
    }

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

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

            workflow_steps.append({
                "step": 1,
                "action": "Connect to Chrome via CDP",
                "command": f'python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); browser = p.chromium.connect_over_cdp(\\"http://localhost:{CDP_PORT}\\")"',
                "prerequisite": f'Chrome must be launched with: chrome.exe --remote-debugging-port={CDP_PORT}'
            })

            # Get or create a page
            ctx = browser.contexts[0] if browser.contexts else browser.new_context()
            pages = ctx.pages
            log(f"Existing pages: {len(pages)}")
            for p_item in pages:
                log(f"  - {p_item.url}")

            # Create new page for clean state
            page = ctx.new_page()
            log("Created new page for Gemini session")

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

            # Navigate to Gemini
            log("\n[STEP 2] Navigating to gemini.google.com...")
            page.goto("https://gemini.google.com", timeout=45000, wait_until="domcontentloaded")
            time.sleep(7)  # Extended wait for full JS load
            screenshot(page, "FINAL_01_loaded")

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

            # Check login state comprehensively
            log("\n[STEP 3] Detecting login state...")

            login_info = page.evaluate("""
                () => {
                    // Check multiple login signals
                    const signals = {
                        // Google account avatar
                        hasAvatar: !!document.querySelector('img[data-iml], [data-ogsr-up] img, [class*="avatar"] img'),

                        // Account dropdown button
                        hasAccountButton: !!document.querySelector(
                            '[aria-label*="Google Account"], [aria-label*="account"]'
                        ),

                        // Sign in button (negative signal)
                        hasSignIn: !!Array.from(document.querySelectorAll('button, a')).find(el => el.textContent?.trim() === 'Sign in'),

                        // User profile area
                        hasProfileArea: !!document.querySelector(
                            '[class*="profile"], [class*="user-info"], [data-ogsr]'
                        ),

                        // Gemini advanced features (appear when logged in)
                        hasHistory: !!document.querySelector('[aria-label*="history"], [class*="conversation-list"]'),

                        // Check page title for user info
                        title: document.title,

                        // Get text of potential account element
                        accountText: document.querySelector('[data-ogsr-up]')?.textContent?.trim()?.substring(0, 50),

                        // All visible buttons (for analysis)
                        buttons: Array.from(document.querySelectorAll('button, a')).filter(el => {
                            const r = el.getBoundingClientRect();
                            return r.width > 0 && r.height > 0;
                        }).map(el => ({
                            text: el.textContent?.trim()?.substring(0, 40),
                            aria: el.getAttribute('aria-label')?.substring(0, 40),
                        })).filter(el => el.text || el.aria).slice(0, 30)
                    };
                    return signals;
                }
            """)

            log(f"Login signals:")
            log(f"  hasAvatar: {login_info.get('hasAvatar')}")
            log(f"  hasAccountButton: {login_info.get('hasAccountButton')}")
            log(f"  hasSignIn: {login_info.get('hasSignIn')}")
            log(f"  hasProfileArea: {login_info.get('hasProfileArea')}")
            log(f"  hasHistory: {login_info.get('hasHistory')}")
            log(f"  title: {login_info.get('title')}")

            log("\nVisible buttons:")
            for btn in login_info.get('buttons', []):
                log(f"  - '{btn.get('text','')}' / '{btn.get('aria','')}'")

            is_logged_in = any([
                login_info.get('hasAvatar'),
                login_info.get('hasAccountButton'),
                login_info.get('hasProfileArea'),
                login_info.get('hasHistory'),
                not login_info.get('hasSignIn'),
            ])

            result["logged_in"] = is_logged_in
            log(f"\nLOGIN STATE: {'LOGGED IN' if is_logged_in else 'NOT LOGGED IN'}")
            screenshot(page, "FINAL_02_login_state")

            if not is_logged_in:
                log("[WARN] Not logged in to Gemini!", "WARN")
                log("[INFO] Thinking/Pro modes won't be available without login", "WARN")

            # Check mode picker
            log("\n[STEP 4] Analyzing mode picker and Deep Think availability...")

            mode_picker = page.locator('[aria-label="Open mode picker"]')
            mode_picker_text = "NOT FOUND"

            if mode_picker.count() > 0:
                mode_picker_text = mode_picker.text_content() or "unknown"
                log(f"Mode picker found: '{mode_picker_text}'")

                mode_picker.click()
                time.sleep(2.5)
                screenshot(page, "FINAL_03_mode_dropdown")

                # Get ALL details about mode options
                mode_data = page.evaluate("""
                    () => {
                        const opts = document.querySelectorAll('[role="menuitemradio"], [data-mode-id]');
                        if (opts.length === 0) {
                            // Try alternative selectors
                            const allBtns = document.querySelectorAll('button[disabled], button:not([disabled])');
                            // Look in the overlay
                            const overlay = document.querySelector('.cdk-overlay-container');
                            if (overlay) {
                                const btns = overlay.querySelectorAll('button');
                                return Array.from(btns).map(el => ({
                                    text: el.textContent?.trim()?.substring(0, 100),
                                    aria: el.getAttribute('aria-label'),
                                    role: el.getAttribute('role'),
                                    disabled: el.getAttribute('aria-disabled') === 'true' || el.disabled,
                                    'data-mode-id': el.getAttribute('data-mode-id'),
                                    'data-test-id': el.getAttribute('data-test-id'),
                                    visible: el.getBoundingClientRect().width > 0,
                                    x: Math.round(el.getBoundingClientRect().x),
                                    y: Math.round(el.getBoundingClientRect().y),
                                }));
                            }
                        }
                        return Array.from(opts).map(el => ({
                            text: el.textContent?.trim()?.substring(0, 100),
                            aria: el.getAttribute('aria-label'),
                            role: el.getAttribute('role'),
                            disabled: el.getAttribute('aria-disabled') === 'true' || el.disabled,
                            'data-mode-id': el.getAttribute('data-mode-id'),
                            'data-test-id': el.getAttribute('data-test-id'),
                            visible: el.getBoundingClientRect().width > 0,
                            x: Math.round(el.getBoundingClientRect().x),
                            y: Math.round(el.getBoundingClientRect().y),
                        }));
                    }
                """)

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

                # Categorize modes
                result["deep_think_modes"] = {}
                for opt in mode_data:
                    if opt.get('text'):
                        test_id = opt.get('data-test-id', 'unknown')
                        result["deep_think_modes"][test_id] = {
                            "text": opt.get('text'),
                            "available": not opt.get('disabled'),
                            "mode_id": opt.get('data-mode-id'),
                        }

                # Try to select best available mode
                available_modes = [opt for opt in mode_data if not opt.get('disabled') and opt.get('visible')]
                thinking_modes = [opt for opt in available_modes if
                                  any(x in (opt.get('text') or '').lower()
                                      for x in ['thinking', 'pro', 'deep think', 'reason'])]

                if thinking_modes:
                    target = thinking_modes[-1]  # Take the most advanced available
                    log(f"\n[OK] Selecting thinking mode: '{target.get('text')}'")
                    page.mouse.click(target['x'] + 30, target['y'] + 10)
                    time.sleep(2)
                    screenshot(page, "FINAL_04_mode_selected")
                    result["mode_selected"] = target.get('text')
                    result["deep_think_found"] = True

                    workflow_steps.append({
                        "step": 4,
                        "action": "Select Deep Think mode",
                        "mode_selected": 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": "Requires Gemini Advanced subscription"
                    })
                else:
                    locked_modes = [opt.get('text') for opt in mode_data if opt.get('disabled')]
                    log(f"[INFO] All thinking modes locked. Locked: {locked_modes}")
                    log("[INFO] Using Fast mode (default)")
                    page.keyboard.press("Escape")
                    result["mode_selected"] = "Fast (default - no subscription)"
                    result["subscription_gate"] = {
                        "status": "locked",
                        "message": "Thinking and Pro modes require Gemini Advanced subscription",
                        "locked_modes": locked_modes,
                        "available_modes": [opt.get('text') for opt in available_modes],
                        "action_required": "Subscribe to Google One AI Premium at one.google.com"
                    }

                workflow_steps.append({
                    "step": 4,
                    "action": "Mode picker analysis",
                    "modes_found": [opt.get('text') for opt in mode_data],
                    "modes_available": [opt.get('text') for opt in available_modes],
                    "selector_pattern": '[role="menuitemradio"]',
                    "note": "Thinking=standard thinking, Pro=extended thinking (Deep Think)"
                })
            else:
                log("[WARN] Mode picker not found", "WARN")

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

            # Enter the test prompt
            log(f"\n[STEP 5] Entering strategic prompt...")

            # Primary input selector (confirmed working)
            input_el = page.locator('[aria-label="Enter a prompt for Gemini"]')
            if input_el.count() == 0:
                input_el = page.locator('div[contenteditable="true"]').first

            if input_el.count() > 0 and input_el.is_visible():
                log("[OK] Found input area")
                input_el.click()
                time.sleep(0.5)
                page.keyboard.type(TEST_PROMPT, delay=20)
                time.sleep(1.5)
                screenshot(page, "FINAL_06_prompt_entered")
                log(f"Prompt typed: '{TEST_PROMPT[:60]}...'")

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

                # Submit
                send_btn = page.locator('[aria-label="Send message"]')
                if send_btn.count() > 0 and send_btn.is_visible():
                    send_btn.click()
                    log("[OK] Clicked Send button")
                else:
                    page.keyboard.press("Enter")
                    log("[OK] Submitted via Enter")

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

                time.sleep(5)
                screenshot(page, "FINAL_07_submitted")

                # Wait for response
                wait_time = 180 if result.get("deep_think_found") else 60
                log(f"\n[STEP 6] Waiting for response (up to {wait_time}s)...")
                if result.get("deep_think_found"):
                    log("Deep Think mode active - expecting extended thinking time...")

                prev_text = ""
                stable_count = 0
                full_response = ""
                thinking_shown = False

                for i in range(wait_time // 2):
                    time.sleep(2)
                    elapsed = (i + 1) * 2

                    # Get current response
                    page_state = page.evaluate("""
                        () => {
                            // Get response text
                            const responses = document.querySelectorAll('model-response');
                            const responseText = Array.from(responses)
                                .map(r => r.innerText || '')
                                .join('\\n');

                            // Check for thinking block
                            const thinkingBlock = document.querySelector(
                                '[class*="thinking"], [class*="thought"], [data-type="thinking"]'
                            );

                            // Check generating state
                            const isGenerating = !!(
                                document.querySelector('[aria-busy="true"]') ||
                                document.querySelector('.generating') ||
                                document.querySelector('[class*="loading-dots"]')
                            );

                            return {
                                responseText: responseText,
                                hasThinkingBlock: !!thinkingBlock,
                                thinkingText: thinkingBlock?.innerText?.substring(0, 200),
                                isGenerating: isGenerating,
                                responseCount: responses.length,
                            };
                        }
                    """)

                    response_text = page_state.get('responseText', '')
                    is_generating = page_state.get('isGenerating', False)
                    has_thinking = page_state.get('hasThinkingBlock', False)

                    if has_thinking and not thinking_shown:
                        log(f"[OK] Thinking block detected: {page_state.get('thinkingText', '')[:100]}")
                        thinking_shown = True
                        screenshot(page, "FINAL_THINKING_BLOCK")

                    if response_text == prev_text:
                        stable_count += 1
                    else:
                        stable_count = 0
                        prev_text = response_text
                        full_response = response_text

                    if elapsed % 10 == 0:
                        log(f"  {elapsed}s: response_len={len(response_text)}, generating={is_generating}, thinking={has_thinking}, stable={stable_count}")

                    if elapsed % 30 == 0:
                        screenshot(page, f"FINAL_progress_{elapsed:03d}s")

                    # Completion check
                    if (stable_count >= 5 and not is_generating and
                        elapsed > 20 and len(response_text) > 200):
                        log(f"[OK] Response complete at {elapsed}s!")
                        full_response = response_text
                        break

                screenshot(page, "FINAL_08_response_complete")
                result["response_text"] = full_response
                result["status"] = "success" if len(full_response) > 100 else "partial"
                log(f"\nResponse length: {len(full_response)} chars")
                log(f"Preview:\n{full_response[:500]}")

            else:
                log("[ERROR] Could not find input area!", "ERROR")
                result["errors"].append("Input not found")
                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, "FINAL_ERROR")
            except:
                pass

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

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

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

    log(f"\nAll results saved to: {results_path}")
    return result


if __name__ == "__main__":
    result = run()
    print(f"\n{'='*60}")
    print(f"FINAL STATUS: {result.get('status')}")
    print(f"LOGGED IN: {result.get('logged_in')}")
    print(f"MODE SELECTED: {result.get('mode_selected')}")
    print(f"DEEP THINK FOUND: {result.get('deep_think_found')}")
    if result.get('subscription_gate'):
        print(f"\nSUBSCRIPTION GATE:")
        for k, v in result['subscription_gate'].items():
            print(f"  {k}: {v}")
    if result.get('deep_think_modes'):
        print(f"\nMODE AVAILABILITY:")
        for k, v in result['deep_think_modes'].items():
            status = "AVAILABLE" if v.get('available') else "LOCKED"
            print(f"  [{status}] {v.get('text')} (id={v.get('mode_id','')})")
    if result.get('response_text'):
        print(f"\nFULL RESPONSE ({len(result['response_text'])} chars):")
        print(result['response_text'])
