#!/usr/bin/env python3
"""
TalkingWidget.ai Comprehensive QA Test Battery
All 8 tests documented with pass/fail results.
"""

import time
import json
import re
from datetime import datetime
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout

REPORT_DIR = "/mnt/e/genesis-system/qa_reports"
TARGET_URL = "https://talkingwidget.ai"

results = []

def log(msg):
    ts = datetime.now().strftime("%H:%M:%S")
    print(f"[{ts}] {msg}")

def record(test_id, name, status, notes="", screenshot=None):
    emoji = "PASS" if status == "PASS" else "FAIL"
    results.append({
        "id": test_id,
        "name": name,
        "status": status,
        "notes": notes,
        "screenshot": screenshot,
        "emoji": emoji
    })
    log(f"[{emoji}] Test {test_id}: {name} — {notes}")

def run_tests():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True, args=["--no-sandbox", "--disable-dev-shm-usage"])

        # ─────────────────────────────────────────────
        # TEST 1: Page Load & Performance
        # ─────────────────────────────────────────────
        log("=== TEST 1: Page Load & Performance ===")
        context = browser.new_context(viewport={"width": 1440, "height": 900})
        page = context.new_page()

        console_errors = []
        page.on("console", lambda msg: console_errors.append(msg.text) if msg.type == "error" else None)

        t1_start = time.time()
        try:
            response = page.goto(TARGET_URL, wait_until="networkidle", timeout=30000)
            t1_elapsed = round(time.time() - t1_start, 2)
            http_status = response.status if response else "No response"

            ss_path = f"{REPORT_DIR}/tw_test1_fullpage.png"
            page.screenshot(path=ss_path, full_page=True)

            status_ok = (http_status == 200)
            time_ok = (t1_elapsed < 15)  # reasonable threshold

            test1_pass = status_ok and time_ok
            record(
                1, "Page Load & Performance",
                "PASS" if test1_pass else "FAIL",
                f"HTTP {http_status} | Load time: {t1_elapsed}s | Console errors: {len(console_errors)}",
                ss_path
            )
        except PlaywrightTimeout:
            record(1, "Page Load & Performance", "FAIL", "Timeout waiting for networkidle", None)
            t1_elapsed = -1
        except Exception as e:
            record(1, "Page Load & Performance", "FAIL", str(e), None)

        # ─────────────────────────────────────────────
        # TEST 2: Navigation Links
        # ─────────────────────────────────────────────
        log("=== TEST 2: Navigation Links ===")
        try:
            # Reload to ensure fresh state
            page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=20000)
            page.wait_for_timeout(2000)

            # Check nav links
            nav_html = page.content()

            login_present = bool(
                page.query_selector("a[href*='login']") or
                page.query_selector("a[href*='signin']") or
                page.evaluate("() => [...document.querySelectorAll('a, button')].some(el => el.textContent.toLowerCase().includes('login') || el.textContent.toLowerCase().includes('sign in'))")
            )

            get_started_present = bool(
                page.query_selector("a[href*='signup']") or
                page.query_selector("a[href*='register']") or
                page.evaluate("() => [...document.querySelectorAll('a, button')].some(el => el.textContent.toLowerCase().includes('get started') || el.textContent.toLowerCase().includes('sign up'))")
            )

            # Screenshot nav area (top of page)
            ss_path = f"{REPORT_DIR}/tw_test2_nav.png"
            page.screenshot(path=ss_path, clip={"x": 0, "y": 0, "width": 1440, "height": 120})

            nav_ok = login_present or get_started_present
            record(
                2, "Navigation Links",
                "PASS" if nav_ok else "FAIL",
                f"Login button: {login_present} | Get Started button: {get_started_present}",
                ss_path
            )
        except Exception as e:
            record(2, "Navigation Links", "FAIL", str(e), None)

        # ─────────────────────────────────────────────
        # TEST 3: Pricing Section
        # ─────────────────────────────────────────────
        log("=== TEST 3: Pricing Section ===")
        try:
            page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=20000)
            page.wait_for_timeout(2000)

            # Scroll through page to find pricing
            page_text = page.evaluate("() => document.body.innerText")

            # Check for correct pricing tiers
            has_starter_497 = "$497" in page_text and ("starter" in page_text.lower() or "Starter" in page_text)
            has_highuse_997 = "$997" in page_text and ("high" in page_text.lower() or "High-Use" in page_text or "High Use" in page_text)
            has_enterprise_1497 = "$1,497" in page_text or "$1497" in page_text

            # FAIL condition: old pricing $297
            has_old_pricing_297 = "$297" in page_text

            # Scroll to pricing section
            page.evaluate("""
                () => {
                    const els = [...document.querySelectorAll('*')];
                    const pricing = els.find(el => el.textContent.includes('$497') || el.textContent.includes('Starter') || el.id === 'pricing' || el.className.toLowerCase().includes('pricing'));
                    if (pricing) pricing.scrollIntoView({behavior: 'instant', block: 'center'});
                }
            """)
            page.wait_for_timeout(1000)

            ss_path = f"{REPORT_DIR}/tw_test3_pricing.png"
            page.screenshot(path=ss_path)

            pricing_ok = has_starter_497 and has_highuse_997 and has_enterprise_1497 and not has_old_pricing_297

            notes = (
                f"$497 Starter: {has_starter_497} | "
                f"$997 High-Use: {has_highuse_997} | "
                f"$1497 Enterprise: {has_enterprise_1497} | "
                f"OLD $297 present: {has_old_pricing_297}"
            )

            # Extract actual prices found
            prices_found = re.findall(r'\$[\d,]+', page_text)
            prices_unique = sorted(set(prices_found))
            notes += f" | All prices found: {prices_unique}"

            record(3, "Pricing Section", "PASS" if pricing_ok else "FAIL", notes, ss_path)
        except Exception as e:
            record(3, "Pricing Section", "FAIL", str(e), None)

        # ─────────────────────────────────────────────
        # TEST 4: Voice Widget Presence
        # ─────────────────────────────────────────────
        log("=== TEST 4: Voice Widget Presence ===")
        try:
            page.goto(TARGET_URL, wait_until="networkidle", timeout=30000)
            page.wait_for_timeout(3000)

            # Check for telnyx-ai-agent element
            telnyx_element = page.query_selector("telnyx-ai-agent")
            telnyx_in_html = "telnyx" in page.content().lower()

            # Check for Telnyx SDK script
            scripts = page.evaluate("""
                () => [...document.querySelectorAll('script')].map(s => s.src || s.textContent.substring(0, 100)).filter(Boolean)
            """)
            telnyx_sdk_loaded = any("telnyx" in str(s).lower() for s in scripts)

            # Check console errors related to telnyx
            telnyx_errors = [e for e in console_errors if "telnyx" in e.lower()]

            # Screenshot widget area - scroll to bottom where widget usually is
            page.evaluate("() => window.scrollTo(0, document.body.scrollHeight * 0.7)")
            page.wait_for_timeout(1000)
            ss_path = f"{REPORT_DIR}/tw_test4_widget.png"
            page.screenshot(path=ss_path)

            widget_ok = telnyx_element is not None or telnyx_in_html or telnyx_sdk_loaded

            record(
                4, "Voice Widget Presence",
                "PASS" if widget_ok else "FAIL",
                f"telnyx-ai-agent element: {telnyx_element is not None} | Telnyx in HTML: {telnyx_in_html} | SDK loaded: {telnyx_sdk_loaded} | Telnyx errors: {len(telnyx_errors)}",
                ss_path
            )
        except Exception as e:
            record(4, "Voice Widget Presence", "FAIL", str(e), None)

        # ─────────────────────────────────────────────
        # TEST 5: Mobile Responsive (iPhone 375x812)
        # ─────────────────────────────────────────────
        log("=== TEST 5: Mobile Responsive ===")
        try:
            mobile_context = browser.new_context(
                viewport={"width": 375, "height": 812},
                user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"
            )
            mobile_page = mobile_context.new_page()
            mobile_page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=20000)
            mobile_page.wait_for_timeout(2000)

            ss_path = f"{REPORT_DIR}/tw_test5_mobile.png"
            mobile_page.screenshot(path=ss_path, full_page=True)

            # Check for horizontal scroll
            scroll_width = mobile_page.evaluate("() => document.documentElement.scrollWidth")
            client_width = mobile_page.evaluate("() => document.documentElement.clientWidth")
            has_horiz_scroll = scroll_width > client_width + 5  # 5px tolerance

            # Check viewport meta tag
            viewport_meta = mobile_page.evaluate("""
                () => {
                    const meta = document.querySelector('meta[name="viewport"]');
                    return meta ? meta.getAttribute('content') : null;
                }
            """)

            mobile_ok = not has_horiz_scroll
            record(
                5, "Mobile Responsive (375x812)",
                "PASS" if mobile_ok else "FAIL",
                f"Horizontal scroll: {has_horiz_scroll} (scrollWidth={scroll_width}, clientWidth={client_width}) | Viewport meta: {viewport_meta}",
                ss_path
            )
            mobile_context.close()
        except Exception as e:
            record(5, "Mobile Responsive (375x812)", "FAIL", str(e), None)

        # ─────────────────────────────────────────────
        # TEST 6: Demo Section
        # ─────────────────────────────────────────────
        log("=== TEST 6: Demo Section ===")
        try:
            page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=20000)
            page.wait_for_timeout(2000)

            page_text_lower = page.evaluate("() => document.body.innerText.toLowerCase()")

            # Look for demo section
            demo_keywords = ["see it in action", "demo", "try it", "watch", "live demo", "hear it"]
            demo_found = any(kw in page_text_lower for kw in demo_keywords)

            # Try to scroll to demo section
            scrolled = page.evaluate("""
                () => {
                    const headings = [...document.querySelectorAll('h1,h2,h3,h4,section,div')];
                    const demo = headings.find(el =>
                        el.textContent.toLowerCase().includes('see it in action') ||
                        el.textContent.toLowerCase().includes('demo') ||
                        el.textContent.toLowerCase().includes('try it') ||
                        el.textContent.toLowerCase().includes('watch') ||
                        el.textContent.toLowerCase().includes('live demo')
                    );
                    if (demo) {
                        demo.scrollIntoView({behavior: 'instant', block: 'center'});
                        return demo.textContent.substring(0, 80);
                    }
                    return null;
                }
            """)

            page.wait_for_timeout(1000)
            ss_path = f"{REPORT_DIR}/tw_test6_demo.png"
            page.screenshot(path=ss_path)

            record(
                6, "Demo Section",
                "PASS" if demo_found else "FAIL",
                f"Demo content found: {demo_found} | Element text: {scrolled} | Keywords checked: {demo_keywords}",
                ss_path
            )
        except Exception as e:
            record(6, "Demo Section", "FAIL", str(e), None)

        # ─────────────────────────────────────────────
        # TEST 7: Footer Links
        # ─────────────────────────────────────────────
        log("=== TEST 7: Footer Links ===")
        try:
            page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=20000)
            page.wait_for_timeout(2000)

            # Scroll to footer
            page.evaluate("() => window.scrollTo(0, document.body.scrollHeight)")
            page.wait_for_timeout(1500)

            # Check for Terms and Privacy links
            links = page.evaluate("""
                () => [...document.querySelectorAll('a')].map(a => ({
                    text: a.textContent.trim().toLowerCase(),
                    href: a.href
                }))
            """)

            terms_link = next((l for l in links if
                "terms" in l["text"] or
                "terms" in (l["href"] or "").lower() or
                "tos" in (l["href"] or "").lower()), None)

            privacy_link = next((l for l in links if
                "privacy" in l["text"] or
                "privacy" in (l["href"] or "").lower()), None)

            ss_path = f"{REPORT_DIR}/tw_test7_footer.png"
            # Screenshot bottom of page
            page_height = page.evaluate("() => document.body.scrollHeight")
            viewport_h = 900
            clip_y = max(0, page_height - viewport_h)
            page.screenshot(path=ss_path, clip={"x": 0, "y": clip_y, "width": 1440, "height": viewport_h})

            footer_ok = terms_link is not None and privacy_link is not None
            record(
                7, "Footer Links",
                "PASS" if footer_ok else "FAIL",
                f"Terms: {terms_link} | Privacy: {privacy_link}",
                ss_path
            )
        except Exception as e:
            record(7, "Footer Links", "FAIL", str(e), None)

        # ─────────────────────────────────────────────
        # TEST 8: CTA Buttons
        # ─────────────────────────────────────────────
        log("=== TEST 8: CTA Buttons ===")
        try:
            page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=20000)
            page.wait_for_timeout(2000)

            # Find primary CTA buttons
            cta_keywords = [
                "get your talking widget",
                "get started",
                "start free",
                "try for free",
                "get talking widget",
                "launch your widget",
                "book a demo",
                "get demo",
                "start now"
            ]

            all_buttons = page.evaluate("""
                () => [...document.querySelectorAll('a, button')].map(el => ({
                    text: el.textContent.trim(),
                    tag: el.tagName,
                    href: el.href || '',
                    visible: el.offsetParent !== null
                })).filter(el => el.text.length > 0 && el.text.length < 100)
            """)

            cta_found = None
            for btn in all_buttons:
                btn_text_lower = btn["text"].lower()
                if any(kw in btn_text_lower for kw in cta_keywords):
                    cta_found = btn
                    break

            # Also check if any button-like element is clickable
            visible_ctaish = [b for b in all_buttons if
                b["visible"] and any(kw in b["text"].lower() for kw in ["get", "start", "try", "launch", "book", "demo", "widget"])
            ]

            # Scroll to first CTA and screenshot
            if cta_found:
                page.evaluate(f"""
                    () => {{
                        const els = [...document.querySelectorAll('a, button')];
                        const cta = els.find(el => el.textContent.includes("{cta_found['text'][:30]}"));
                        if (cta) cta.scrollIntoView({{behavior: 'instant', block: 'center'}});
                    }}
                """)
                page.wait_for_timeout(500)

            ss_path = f"{REPORT_DIR}/tw_test8_cta.png"
            page.screenshot(path=ss_path)

            cta_ok = cta_found is not None or len(visible_ctaish) > 0
            record(
                8, "CTA Buttons",
                "PASS" if cta_ok else "FAIL",
                f"Primary CTA found: {cta_found} | CTA-like visible buttons: {len(visible_ctaish)} | Sample: {[b['text'] for b in visible_ctaish[:5]]}",
                ss_path
            )
        except Exception as e:
            record(8, "CTA Buttons", "FAIL", str(e), None)

        browser.close()

    # ─────────────────────────────────────────────
    # Print Summary Table
    # ─────────────────────────────────────────────
    print("\n" + "="*80)
    print("TALKINGWIDGET.AI QA TEST RESULTS SUMMARY")
    print("="*80)
    print(f"{'Test':<5} {'Name':<35} {'Status':<6} {'Screenshot'}")
    print("-"*80)
    passes = 0
    fails = 0
    for r in results:
        status_disp = r['status']
        ss = r['screenshot'] or "N/A"
        print(f"{r['id']:<5} {r['name']:<35} {status_disp:<6} {ss}")
        if r['status'] == 'PASS':
            passes += 1
        else:
            fails += 1
    print("-"*80)
    print(f"TOTAL: {passes} PASS / {fails} FAIL out of {len(results)} tests")
    print("="*80)

    print("\n\nDETAILED NOTES:")
    for r in results:
        print(f"\nTest {r['id']}: {r['name']}")
        print(f"  Status: {r['status']}")
        print(f"  Notes:  {r['notes']}")

    # Save JSON results
    json_path = f"{REPORT_DIR}/tw_qa_results.json"
    with open(json_path, "w") as f:
        json.dump({
            "timestamp": datetime.now().isoformat(),
            "target": TARGET_URL,
            "summary": {"pass": passes, "fail": fails, "total": len(results)},
            "results": results
        }, f, indent=2)
    print(f"\nResults JSON saved to: {json_path}")

    return results

if __name__ == "__main__":
    run_tests()
