#!/usr/bin/env python3
"""
Genesis Browser Test Suite — Playwright-based E2E tests for ReceptionistAI stack

Tests:
1. Voice widget demo page loads correctly
2. Telnyx widget renders (telnyx-ai-agent element present)
3. GHL webhook endpoint responds
4. Sunaiva API health check passes
5. ReceptionistAI API endpoints respond

Usage:
    pytest tests/browser_test_suite.py
    pytest tests/browser_test_suite.py -v --headed
    pytest tests/browser_test_suite.py -k "test_voice_widget"
"""

import pytest
from playwright.sync_api import Page, expect
import requests
import os

# === TEST CONFIGURATION ===
VOICE_WIDGET_DEMO = "https://sunaivadigital.com/talking-widget/demo-v2.html"
SUNAIVA_API = "https://api.sunaivadigital.com"
GHL_WEBHOOK_BASE = "https://api.sunaivadigital.com/webhooks/ghl"
RECEPTIONISTAI_API = "https://api.receptionistai.au"

# Telnyx AI Assistant ID (from loop/tasks.json context)
TELNYX_ASSISTANT_ID = "assistant-9c42d3ce-e05a-4e34-8083-c91081917637"


# === FIXTURES ===
@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
    """Configure browser with realistic user agent and permissions"""
    return {
        **browser_context_args,
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
        "viewport": {"width": 1920, "height": 1080},
        "permissions": ["microphone"],  # Voice widget needs mic access
    }


# === BROWSER TESTS ===
class TestVoiceWidget:
    """Test suite for Telnyx voice widget integration"""

    def test_voice_widget_page_loads(self, page: Page):
        """Voice widget demo page loads without errors"""
        # Navigate to demo page
        response = page.goto(VOICE_WIDGET_DEMO)
        assert response is not None, "Page failed to load"
        assert response.status == 200, f"HTTP {response.status} error"

        # Check page title
        expect(page).to_have_title("Telnyx AI Agent Demo")

        # Ensure no console errors
        console_errors = []
        page.on("console", lambda msg: console_errors.append(msg) if msg.type == "error" else None)
        page.wait_for_timeout(2000)  # Wait for JS to execute
        assert len(console_errors) == 0, f"Console errors detected: {console_errors}"

    def test_telnyx_widget_renders(self, page: Page):
        """Telnyx <telnyx-ai-agent> custom element is present and initialized"""
        page.goto(VOICE_WIDGET_DEMO)
        page.wait_for_timeout(3000)  # Wait for Telnyx SDK to load

        # Check for telnyx-ai-agent element
        widget = page.locator("telnyx-ai-agent")
        expect(widget).to_be_attached()

        # Verify assistant ID is set correctly
        assistant_attr = widget.get_attribute("assistant-id")
        assert assistant_attr == TELNYX_ASSISTANT_ID, \
            f"Assistant ID mismatch: expected {TELNYX_ASSISTANT_ID}, got {assistant_attr}"

        # Check widget is visible (not display:none)
        expect(widget).to_be_visible()

    def test_widget_call_button_interactive(self, page: Page):
        """Voice widget call button is clickable"""
        page.goto(VOICE_WIDGET_DEMO)
        page.wait_for_timeout(3000)

        # Look for call button (inside shadow DOM of telnyx-ai-agent)
        # Telnyx widget exposes a call button — we can't pierce shadow DOM easily,
        # so check that clicking the widget doesn't throw errors
        widget = page.locator("telnyx-ai-agent")
        widget.click()

        # Check for error modal or console errors
        page.wait_for_timeout(1000)
        error_modal = page.locator(".error, .alert-danger, [role='alert']")
        expect(error_modal).to_have_count(0)


class TestAPIEndpoints:
    """Test suite for API health checks"""

    def test_sunaiva_api_health(self):
        """Sunaiva API /health endpoint responds"""
        response = requests.get(f"{SUNAIVA_API}/health", timeout=10)
        assert response.status_code == 200, f"Health check failed: {response.status_code}"

        data = response.json()
        assert data.get("status") == "ok", f"Unhealthy API: {data}"

    def test_ghl_webhook_endpoint_exists(self):
        """GHL webhook endpoint returns 405 (POST required) or 200"""
        # Webhook expects POST, but GET should not 404
        response = requests.get(f"{GHL_WEBHOOK_BASE}/contact", timeout=10)
        assert response.status_code in [200, 405], \
            f"Webhook endpoint not found: {response.status_code}"

    @pytest.mark.skipif(
        os.getenv("SKIP_EXTERNAL_API") == "1",
        reason="External API test disabled"
    )
    def test_receptionistai_api_reachable(self):
        """ReceptionistAI API is reachable"""
        try:
            response = requests.get(f"{RECEPTIONISTAI_API}/health", timeout=10)
            assert response.status_code in [200, 404], \
                "ReceptionistAI API unreachable"
        except requests.exceptions.RequestException as e:
            pytest.fail(f"ReceptionistAI API connection failed: {e}")


class TestIntegrationFlow:
    """Integration tests for end-to-end flows"""

    def test_widget_to_api_flow(self, page: Page):
        """Voice widget demo page → loads widget → API is healthy"""
        # Step 1: Load demo page
        page.goto(VOICE_WIDGET_DEMO)
        page.wait_for_timeout(3000)

        # Step 2: Verify widget rendered
        widget = page.locator("telnyx-ai-agent")
        expect(widget).to_be_attached()

        # Step 3: Verify backend API is reachable
        response = requests.get(f"{SUNAIVA_API}/health", timeout=5)
        assert response.status_code == 200, "Backend API down during widget load"

        # Integration success
        assert True


# === PERFORMANCE TESTS ===
class TestPerformance:
    """Performance benchmarks for widget loading"""

    def test_widget_loads_within_5_seconds(self, page: Page):
        """Voice widget demo page loads and renders within 5 seconds"""
        import time
        start = time.time()

        page.goto(VOICE_WIDGET_DEMO)
        page.wait_for_selector("telnyx-ai-agent", timeout=5000)

        elapsed = time.time() - start
        assert elapsed < 5.0, f"Widget took {elapsed:.2f}s to load (>5s threshold)"


# === SECURITY TESTS ===
class TestSecurity:
    """Security checks for widget and API"""

    def test_no_sensitive_data_in_page_source(self, page: Page):
        """Ensure no API keys or secrets leaked in HTML source"""
        page.goto(VOICE_WIDGET_DEMO)
        content = page.content()

        # Patterns to check for
        forbidden_patterns = [
            "sk_live_",  # Stripe live key
            "sk_test_",  # Stripe test key
            "KEY",       # Generic API key pattern
            "SECRET",    # Generic secret pattern
        ]

        for pattern in forbidden_patterns:
            assert pattern not in content, f"Sensitive data pattern '{pattern}' found in page source"

    def test_https_only(self, page: Page):
        """All pages and assets load over HTTPS"""
        page.goto(VOICE_WIDGET_DEMO)
        page.wait_for_load_state("networkidle")

        # Check for any HTTP resources (should be none)
        http_requests = []
        page.on("request", lambda req: http_requests.append(req.url) if req.url.startswith("http://") else None)
        page.reload()
        page.wait_for_timeout(2000)

        assert len(http_requests) == 0, f"Insecure HTTP requests detected: {http_requests}"


# === ACCESSIBILITY TESTS ===
class TestAccessibility:
    """Basic accessibility checks"""

    def test_page_has_title(self, page: Page):
        """Demo page has a proper title tag"""
        page.goto(VOICE_WIDGET_DEMO)
        expect(page).to_have_title("Telnyx AI Agent Demo")

    def test_no_accessibility_violations(self, page: Page):
        """Run basic accessibility checks (requires axe-core)"""
        pytest.skip("axe-core integration not yet configured")


if __name__ == "__main__":
    pytest.main([__file__, "-v", "--headed"])
