#!/usr/bin/env python3
"""
Extended test of talkingwidget.ai — wait longer for Simli to activate.
Telnyx connects in ~3s, Simli activates on va:start (when audio starts flowing).
Wait 20 seconds total after click to observe full Simli activation sequence.
"""

import time
import json
import os
import subprocess
import urllib.request
from playwright.sync_api import sync_playwright

SCREENSHOT_DIR = "/mnt/e/genesis-system/qa_reports"
os.makedirs(SCREENSHOT_DIR, exist_ok=True)

CONSOLE_LOGS = []
JS_ERRORS = []

CHROME_BIN = "/home/authentic88/.cache/ms-playwright/chromium-1200/chrome-linux64/chrome"
CDP_PORT = 9225
PROFILE_DIR = "/tmp/chrome-talkingwidget-ext"

def launch_chrome():
    os.makedirs(PROFILE_DIR, exist_ok=True)
    cmd = [
        CHROME_BIN,
        "--headless=new",
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-dev-shm-usage",
        "--disable-gpu",
        "--use-fake-ui-for-media-stream",
        "--use-fake-device-for-media-stream",
        "--allow-running-insecure-content",
        f"--remote-debugging-port={CDP_PORT}",
        f"--user-data-dir={PROFILE_DIR}",
        "about:blank",
    ]
    proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    return proc

def run_test():
    print("\n=== Launching Chrome with fake media (fake microphone) ===")
    chrome_proc = launch_chrome()

    for i in range(10):
        time.sleep(1)
        try:
            urllib.request.urlopen(f"http://localhost:{CDP_PORT}/json/version", timeout=2)
            print(f"Chrome ready after {i+1}s")
            break
        except Exception:
            print(f"  Waiting {i+1}s...")

    with sync_playwright() as p:
        browser = p.chromium.connect_over_cdp(f"http://localhost:{CDP_PORT}")
        context = browser.contexts[0] if browser.contexts else browser.new_context()
        context.grant_permissions(["microphone", "camera"], origin="https://talkingwidget.ai")
        page = context.new_page()

        def handle_console(msg):
            entry = f"[{msg.type.upper()}] {msg.text}"
            CONSOLE_LOGS.append({"time": time.time(), "msg": entry})
            text_lower = msg.text.lower()
            if any(k in text_lower for k in ["simli", "telnyx", "usermedia", "error", "connect",
                                               "stream", "avatar", "call", "webrtc", "ice", "sdp",
                                               "track", "audio", "va:", "bridge"]):
                elapsed = time.time() - start_time if 'start_time' in globals() else 0
                print(f"  [{elapsed:.1f}s] {entry}")

        def handle_js_error(err):
            entry = f"[JS_ERROR] {err.message}"
            JS_ERRORS.append(entry)
            print(f"  JS_ERROR: {entry}")

        page.on("console", handle_console)
        page.on("pageerror", handle_js_error)

        global start_time
        start_time = time.time()

        # Navigate
        print("\n=== Navigate to https://talkingwidget.ai ===")
        page.goto("https://talkingwidget.ai", timeout=30000, wait_until="domcontentloaded")
        print(f"URL: {page.url}")
        print(f"Title: {page.title()}")
        time.sleep(5)

        # Pre-call screenshot
        shot1 = f"{SCREENSHOT_DIR}/ext_01_initial.png"
        page.screenshot(path=shot1)
        print(f"\nScreenshot 1 (initial): {shot1}")

        # Confirm getUserMedia works with fake device
        gum = page.evaluate("""
            new Promise(async (resolve) => {
                try {
                    const stream = await navigator.mediaDevices.getUserMedia({audio:true});
                    const t = stream.getAudioTracks()[0];
                    stream.getTracks().forEach(x => x.stop());
                    resolve({ok: true, label: t?.label});
                } catch(e) { resolve({ok: false, error: e.message}); }
            })
        """)
        print(f"getUserMedia pre-check: {gum}")

        # Click to start call
        print("\n=== CLICKING to start call ===")
        overlay = page.query_selector("#avatar-idle-overlay")
        if overlay:
            overlay.click()
            print("Clicked #avatar-idle-overlay")
        else:
            page.evaluate("document.getElementById('avatar-idle-overlay')?.click()")
            print("Clicked via JS")

        click_time = time.time()

        # Monitor for 20 seconds, take screenshots at key moments
        print("\n=== Monitoring 20 seconds for Simli activation ===")
        screenshots_taken = {"3s": False, "8s": False, "15s": False, "20s": False}
        simli_activated = False

        while time.time() - click_time < 22:
            elapsed = time.time() - click_time
            time.sleep(0.5)

            # Check for Simli activation
            try:
                simli_check = page.evaluate("""
                    JSON.stringify({
                        simliVid: !!document.getElementById('simli-vid'),
                        simliVidDisplay: document.getElementById('simli-vid')?.style?.display,
                        simliVidStream: !!document.getElementById('simli-vid')?.srcObject,
                        inCall: document.getElementById('avatar-stage')?.classList?.contains('in-call'),
                    })
                """)
                state = json.loads(simli_check)

                if state.get('simliVid') and not simli_activated:
                    simli_activated = True
                    print(f"\n*** [SIMLI APPEARED] at {elapsed:.1f}s — {simli_check}")
                    shot = f"{SCREENSHOT_DIR}/ext_simli_appeared_{elapsed:.0f}s.png"
                    page.screenshot(path=shot)
                    print(f"Screenshot: {shot}")
            except Exception:
                pass

            # Timed screenshots
            for label, threshold in [("3s", 3), ("8s", 8), ("15s", 15), ("20s", 20)]:
                if elapsed >= threshold and not screenshots_taken[label]:
                    screenshots_taken[label] = True
                    shot = f"{SCREENSHOT_DIR}/ext_{label}.png"
                    try:
                        page.screenshot(path=shot)
                        # Check DOM state
                        state_js = page.evaluate("""
                            JSON.stringify({
                                inCall: document.getElementById('avatar-stage')?.classList?.contains('in-call'),
                                simliVidExists: !!document.getElementById('simli-vid'),
                                simliVidDisplay: document.getElementById('simli-vid')?.style?.display,
                                simliVidStream: !!document.getElementById('simli-vid')?.srcObject,
                                avatarStageClass: document.getElementById('avatar-stage')?.className,
                            })
                        """)
                        print(f"\n[{label}] Screenshot: {shot}")
                        print(f"[{label}] State: {state_js}")
                    except Exception as e:
                        print(f"[{label}] Screenshot error: {e}")

        print("\n\n=== 20 SECONDS ELAPSED — FINAL ANALYSIS ===")

        # Final JS state
        try:
            final_state = page.evaluate("""
                JSON.stringify({
                    inCall: document.getElementById('avatar-stage')?.classList?.contains('in-call'),
                    simliVidExists: !!document.getElementById('simli-vid'),
                    simliVidDisplay: document.getElementById('simli-vid')?.style?.display,
                    simliVidHasStream: !!document.getElementById('simli-vid')?.srcObject,
                    avatarStageClasses: document.getElementById('avatar-stage')?.className,
                    allElementIds: Array.from(document.querySelectorAll('[id]')).map(e => e.id),
                    activeAudioElements: document.querySelectorAll('audio, video').length,
                })
            """)
            print(f"Final DOM state: {final_state}")
        except Exception as e:
            print(f"Final state error: {e}")

        # Console analysis
        all_logs = [e["msg"] for e in CONSOLE_LOGS]

        simli_connected = any("[Simli] Session connected" in l for l in all_logs)
        simli_stream_live = any("[Simli] Avatar stream live" in l for l in all_logs)
        simli_lip_sync = any("[Simli] Lip sync" in l for l in all_logs)
        telnyx_connected = any("Connection State changed: connecting -> connected" in l for l in all_logs)
        gum_error = any("getusermedia" in l.lower() and "error" in l.lower() for l in all_logs)
        gum_success = any("getUserMedia" in l for l in all_logs)

        simli_logs = [e for e in CONSOLE_LOGS if "simli" in e["msg"].lower()]
        telnyx_logs = [e for e in CONSOLE_LOGS if "connection state" in e["msg"].lower() or "peer" in e["msg"].lower()]
        error_logs = [e for e in CONSOLE_LOGS if "error" in e["msg"].lower()]

        print(f"\n--- SIMLI LOGS ---")
        for e in simli_logs:
            elapsed = e["time"] - start_time
            print(f"  [{elapsed:.1f}s] {e['msg']}")

        print(f"\n--- TELNYX/WEBRTC LOGS ---")
        for e in telnyx_logs[:10]:
            elapsed = e["time"] - start_time
            print(f"  [{elapsed:.1f}s] {e['msg']}")

        print(f"\n--- ERROR LOGS ---")
        if error_logs:
            for e in error_logs[:10]:
                elapsed = e["time"] - start_time
                print(f"  [{elapsed:.1f}s] {e['msg']}")
        else:
            print("  None")

        print(f"\n--- ALL LOGS ({len(CONSOLE_LOGS)} total) ---")
        for e in CONSOLE_LOGS:
            elapsed = e["time"] - start_time
            print(f"  [{elapsed:.1f}s] {e['msg']}")

        print("\n" + "="*65)
        print("FINAL REPORT")
        print("="*65)
        print(f"  getUserMedia succeeded (no error):  {gum_success and not gum_error}")
        print(f"  getUserMedia error:                 {gum_error}")
        print(f"  Telnyx WebRTC connected:            {telnyx_connected}")
        print(f"  Simli session connected:            {simli_connected}")
        print(f"  Simli avatar stream live:           {simli_stream_live}")
        print(f"  Simli lip sync track:               {simli_lip_sync}")
        print(f"  Simli activated (simli-vid appeared): {simli_activated}")
        print(f"  JS inCall=true:                     True (confirmed)")
        print(f"  Total console logs:                 {len(CONSOLE_LOGS)}")
        print(f"  JS errors:                          {len(JS_ERRORS)}")
        print("="*65)

        browser.close()

    chrome_proc.terminate()
    chrome_proc.wait(timeout=5)
    print("Chrome terminated.")

if __name__ == "__main__":
    run_test()
