"""Phase 2 browser check: WhatsApp connection, webhooks (through the Next.js proxy), test messages, simulation.
Run against a freshly seeded database with WHATSAPP_PROVIDER=fake:
    python e2e/e2e_whatsapp.py ./e2e-shots
"""
import hashlib, hmac, json, os, re, sys, time
from playwright.sync_api import sync_playwright, expect

OUT = sys.argv[1]
os.makedirs(OUT, exist_ok=True)
BASE = os.environ.get("E2E_BASE", "http://localhost:3000")
SECRET = "a" * 32
errors = []

def shot(page, name):
    page.screenshot(path=f"{OUT}/{name}.png")

def login(page, email, pw="ChangeMe!2026"):
    page.goto(f"{BASE}/login")
    page.fill("#email", email); page.fill("#password", pw); page.click("button[type=submit]")
    page.wait_for_url("**/dashboard")

with sync_playwright() as p:
    b = p.chromium.launch()
    ctx = b.new_context(viewport={"width": 1440, "height": 900})
    page = ctx.new_page()
    page.on("pageerror", lambda e: errors.append(f"pageerror: {e}"))
    login(page, "owner@acme.test")
    nav = page.get_by_role("navigation", name="Main")

    nav.get_by_role("link", name="WhatsApp setup").click()
    expect(page.get_by_role("heading", name="WhatsApp setup")).to_be_visible()
    expect(page.get_by_text("Simulation mode.")).to_be_visible()
    shot(page, "w01-empty")

    # Connect: validation, Meta token error, success
    page.get_by_role("button", exact=True, name="Connect a number").click()
    dlg = page.locator("dialog[open]")
    dlg.get_by_role("button", exact=True, name="Connect number").click()
    expect(dlg.get_by_text("is the numeric ID")).to_have_count(2)
    dlg.locator("#wa-waba").fill("102290129340398")
    dlg.locator("#wa-phone").fill("106540352242922")
    dlg.locator("#wa-token").fill("invalid" + "x" * 30)
    dlg.locator("#wa-secret").fill(SECRET)
    dlg.get_by_role("button", exact=True, name="Connect number").click()
    expect(dlg.get_by_text("Meta rejected the access token")).to_be_visible()
    shot(page, "w02-connect-error")
    dlg.locator("#wa-token").fill("EAAG" + "x" * 60 + "WXYZ")
    dlg.get_by_role("button", exact=True, name="Connect number").click()
    expect(page.get_by_text("Connected +1 555-0129-22")).to_be_visible()
    expect(page.get_by_role("heading", name="+1 555-0129-22")).to_be_visible()
    expect(page.get_by_text("Devwebs Test Business")).to_be_visible()
    expect(page.get_by_text("High quality")).to_be_visible()
    shot(page, "w03-connected-webhook")

    # Webhook verification + signed delivery through the Next.js /api proxy
    field = lambda label: page.get_by_role("button", name=f"Copy {label.lower()}").locator("xpath=preceding-sibling::code")
    callback = field("Callback URL").inner_text()
    path = re.search(r"/api/webhooks/whatsapp/[A-Za-z0-9_-]+", callback).group(0)
    verify_token = field("Verify token").inner_text()
    r = ctx.request.get(f"{BASE}{path}?hub.mode=subscribe&hub.verify_token={verify_token}&hub.challenge=4242")
    assert r.status == 200 and r.text() == "4242", (r.status, r.text())
    payload = {"object": "whatsapp_business_account", "entry": [{"id": "102290129340398", "changes": [{"field": "messages", "value": {
        "messaging_product": "whatsapp", "metadata": {"display_phone_number": "15550129922", "phone_number_id": "106540352242922"},
        "contacts": [{"profile": {"name": "Neha Kapoor"}, "wa_id": "919811122233"}],
        "messages": [{"from": "919811122233", "id": "wamid.E2E1", "timestamp": str(int(time.time())), "type": "text", "text": {"body": "Hi, is the store open on Sunday?"}}]}}]}]}
    raw = json.dumps(payload, separators=(",", ":")).encode()
    sig = "sha256=" + hmac.new(SECRET.encode(), raw, hashlib.sha256).hexdigest()
    bad = ctx.request.post(f"{BASE}{path}", data=raw, headers={"Content-Type": "application/json", "X-Hub-Signature-256": "sha256=" + "0" * 64})
    assert bad.status == 401, bad.status
    ok = ctx.request.post(f"{BASE}{path}", data=raw, headers={"Content-Type": "application/json", "X-Hub-Signature-256": sig})
    assert ok.status == 200, ok.status
    again = ctx.request.post(f"{BASE}{path}", data=raw, headers={"Content-Type": "application/json", "X-Hub-Signature-256": sig})
    assert again.status == 200
    page.reload()
    expect(page.get_by_role("tab", name="Messages")).to_have_attribute("aria-selected", "true")
    expect(page.get_by_text("Hi, is the store open on Sunday?")).to_have_count(1)
    expect(page.get_by_text("Neha Kapoor")).to_be_visible()

    # Test messages: free text allowed now (window open), template to someone else, 24h rule message
    page.get_by_role("tab", name="Test").click()
    page.fill("#t-to", "919812345670")
    page.locator("#t-kind").select_option("text")
    page.fill("#t-text", "Hello")
    page.get_by_role("button", exact=True, name="Send test message").click()
    expect(page.get_by_text("only allows an approved template")).to_be_visible()
    page.locator("#t-kind").select_option("template")
    page.get_by_role("button", exact=True, name="Send test message").click()
    expect(page.get_by_text("Test message sent to Meta")).to_be_visible()
    page.fill("#t-to", "919811122233")
    page.locator("#t-kind").select_option("text")
    page.fill("#t-text", "Yes, 10am to 6pm!")
    page.get_by_role("button", exact=True, name="Send test message").click()
    expect(page.get_by_text("Test message sent to Meta").first).to_be_visible()
    # Simulated inbound STOP opts the contact out
    page.fill("#s-from", "919812345670"); page.fill("#s-text", "STOP")
    page.get_by_role("button", exact=True, name="Receive message").click()
    expect(page.get_by_text("Simulated message received")).to_be_visible()
    shot(page, "w04-test-tab")

    # Messages tab: simulate delivery statuses
    page.get_by_role("tab", name="Messages").click()
    row = page.locator("tr", has_text="Yes, 10am to 6pm!")
    expect(row.get_by_text("Sent to Meta")).to_be_visible()
    row.get_by_role("button", exact=True, name="read").click()
    expect(row.get_by_text("Read", exact=True)).to_be_visible()
    shot(page, "w05-messages")

    page.get_by_role("tab", name="Activity").click()
    expect(page.get_by_text("GET /v26.0/106540352242922").first).to_be_visible()
    expect(page.get_by_text("POST /v26.0/106540352242922/messages").first).to_be_visible()
    expect(page.get_by_text("Meta rejected", exact=False)).to_have_count(0)
    shot(page, "w06-activity")

    # Contact side effects
    nav.get_by_role("link", name="Contacts", exact=True).click()
    page.fill("input[placeholder^='Search']", "Neha")
    expect(page.get_by_role("button", exact=True, name="Neha Kapoor")).to_be_visible()
    page.fill("input[placeholder^='Search']", "Rohan")
    expect(page.locator("tr", has=page.get_by_role("button", exact=True, name="Rohan Mehta")).get_by_text("Opted out")).to_be_visible()

    # Dashboard checklist step done
    nav.get_by_role("link", name="Dashboard").click()
    expect(page.get_by_text("Connect a number")).to_have_count(0)
    shot(page, "w07-dashboard")

    # Rotate credentials, then disconnect and see reconnect prefill
    nav.get_by_role("link", name="WhatsApp setup").click()
    page.get_by_role("button", exact=True, name="Update credentials").click()
    dlg = page.locator("dialog[open]")
    dlg.locator("#wa-token").fill("EAAG" + "y" * 50 + "ROT8")
    dlg.get_by_role("button", exact=True, name="Save credentials").click()
    expect(page.get_by_text("••••ROT8")).to_be_visible()
    page.get_by_role("button", exact=True, name="Disconnect").click()
    page.get_by_role("button", exact=True, name="Disconnect number").click()
    expect(page.get_by_text("Previously connected")).to_be_visible()
    shot(page, "w08-disconnected")
    page.get_by_role("button", exact=True, name="Reconnect").click()
    expect(page.locator("#wa-phone")).to_have_value("106540352242922")
    page.locator("dialog[open]").get_by_role("button", exact=True, name="Cancel").click()

    # Mobile layout check
    m = b.new_context(viewport={"width": 390, "height": 844}, storage_state=ctx.storage_state())
    mp = m.new_page()
    mp.goto(f"{BASE}/settings/whatsapp")
    expect(mp.get_by_text("Previously connected")).to_be_visible()
    if mp.evaluate("document.documentElement.scrollWidth > innerWidth"): errors.append("mobile overflow on WhatsApp setup")
    mp.screenshot(path=f"{OUT}/w09-mobile.png")
    b.close()

print("ERRORS:", errors if errors else "none")
