import os, sys, re
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")
errors = []

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

with sync_playwright() as p:
    b = p.chromium.launch()
    ctx = b.new_context(viewport={"width": 1440, "height": 900}, accept_downloads=True)
    page = ctx.new_page()
    page.on("console", lambda m: m.type == "error" and "Failed to load resource" not in m.text and errors.append(f"console: {m.text}"))  # 4xx from deliberate validation checks are expected
    page.on("pageerror", lambda e: errors.append(f"pageerror: {e}"))

    # Login redirect + bad password
    page.goto(f"{BASE}/contacts")
    expect(page).to_have_url(re.compile(r"/login\?next=%2Fcontacts"))
    page.fill("#email", "owner@acme.test"); page.fill("#password", "wrong-password1")
    page.click("button[type=submit]")
    expect(page.get_by_text("These credentials do not match our records")).to_be_visible()
    shot(page, "01-login-error")
    page.fill("#password", "ChangeMe!2026"); page.click("button[type=submit]")
    expect(page).to_have_url(re.compile(r"/contacts$"))
    expect(page.get_by_role("button", exact=True, name="Piper Reeves")).to_be_visible()
    shot(page, "03-contacts")

    # Dashboard
    page.get_by_role("link", name="Dashboard").click()
    expect(page.get_by_text("Marketing consent")).to_be_visible()
    page.wait_for_timeout(400)
    shot(page, "02-dashboard")

    # Consent deep link
    page.get_by_role("link", name="Opted out").first.click()
    expect(page.get_by_role("button", exact=True, name="Kanchan Kale")).to_be_visible()
    expect(page.get_by_role("button", exact=True, name="Piper Reeves")).to_have_count(0)
    page.get_by_role("button", exact=True, name="Clear").click()

    # Search
    page.fill("input[placeholder^='Search']", "rohan")
    expect(page.get_by_role("button", exact=True, name="Piper Reeves")).to_have_count(0)
    expect(page.get_by_role("button", exact=True, name="Rohan Mehta")).to_be_visible()
    page.fill("input[placeholder^='Search']", "")
    expect(page.get_by_role("button", exact=True, name="Piper Reeves")).to_be_visible()

    # Add contact: validation + duplicate warning + success
    page.get_by_role("button", exact=True, name="Add contact").first.click()
    dlg = page.locator("dialog[open]")
    dlg.get_by_role("button", exact=True, name="Add contact").click()
    expect(dlg.get_by_text("First name is required")).to_be_visible()
    dlg.locator("#cf-phone").fill("919812345670")
    expect(dlg.get_by_text("Already saved as Rohan Mehta")).to_be_visible()
    shot(page, "04-add-contact-duplicate")
    dlg.locator("#cf-first").fill("Meera")
    dlg.locator("#cf-last").fill("Iyer")
    dlg.locator("#cf-phone").fill("+91 99887 76655")
    dlg.locator("#cf-email").fill("meera@example.com")
    dlg.locator("#cf-country").select_option("IN")
    dlg.locator("#cf-lang").fill("ta")
    dlg.get_by_text("VIP Customers").click()
    dlg.locator("#cf-tags").fill("Lead"); dlg.locator("#cf-tags").press("Enter")
    dlg.locator("#cf-consent").select_option("opted_in")
    dlg.locator("#cf-x-city").fill("Chennai")
    shot(page, "05-add-contact-filled")
    dlg.get_by_role("button", exact=True, name="Add contact").click()
    expect(page.get_by_text("Contact added")).to_be_visible()
    expect(page.get_by_role("button", exact=True, name="Meera Iyer")).to_be_visible()

    # Drawer: details, opt out, activity
    page.get_by_role("button", exact=True, name="Meera Iyer").click()
    drawer = page.get_by_role("dialog", name="Contact details")
    expect(drawer.get_by_text("Chennai")).to_be_visible()
    expect(drawer.get_by_text("+919988776655")).to_be_visible()
    drawer.get_by_role("button", exact=True, name="Opt out of marketing").click()
    expect(drawer.get_by_text("Opted out of marketing messages")).to_be_visible()
    shot(page, "06-contact-drawer")

    # Edit from drawer
    drawer.get_by_role("button", exact=True, name="Edit").click()
    dlg = page.locator("dialog[open]")
    dlg.locator("#cf-first").fill("Meera K")
    dlg.get_by_role("button", exact=True, name="Save contact").click()
    expect(page.get_by_text("Contact saved")).to_be_visible()
    drawer = page.get_by_role("dialog", name="Contact details")
    expect(drawer.get_by_role("heading", name="Meera K Iyer")).to_be_visible()
    expect(drawer.get_by_text("Updated first name")).to_be_visible()
    page.keyboard.press("Escape")
    expect(page.get_by_role("dialog", name="Contact details")).to_have_count(0)

    # Bulk: select two, add to Newsletter
    page.get_by_label("Select Piper Reeves").check()
    page.get_by_label("Select Rohan Mehta").check()
    expect(page.get_by_text("2 selected")).to_be_visible()
    page.get_by_label("Group for selected").select_option(label="Newsletter")
    shot(page, "07-bulk-actions")
    page.get_by_role("button", exact=True, name="Add to group").click()
    expect(page.get_by_text("Added 2 contacts to the group")).to_be_visible()

    # Export (download) + template
    page.get_by_role("button", exact=True, name="Export").click()
    with page.expect_download() as d:
        page.get_by_role("button", exact=True, name="Export contacts").click()
    d.value.save_as(f"{OUT}/export.xlsx")
    with page.expect_download() as d2:
        page.get_by_role("button", exact=True, name="Download template").click()
    d2.value.save_as(f"{OUT}/template.xlsx")
    shot(page, "08-export")
    page.locator("dialog[open]").get_by_role("button", exact=True, name="Close").first.click()

    # Import a generated file
    page.get_by_role("button", exact=True, name="Import").click()
    page.set_input_files("input[type=file]", sys.argv[2])
    page.get_by_role("button", exact=True, name="Import contacts").click()
    expect(page.get_by_text("Rows that need attention")).to_be_visible()
    page.wait_for_timeout(600); shot(page, "09-import-result")
    page.get_by_role("button", exact=True, name="Done").click()
    expect(page.get_by_role("button", exact=True, name="Zara Khan")).to_be_visible()

    # Delete with confirmation
    row = page.locator("tr", has=page.get_by_role("button", exact=True, name="Zara Khan"))
    row.get_by_role("button", exact=True, name="Delete").click()
    expect(page.get_by_text("Delete this contact?")).to_be_visible()
    shot(page, "10-delete-confirm")
    page.get_by_role("button", exact=True, name="Delete permanently").click()
    expect(page.get_by_role("button", exact=True, name="Zara Khan")).to_have_count(0)

    # Groups / custom fields / team
    page.get_by_role("link", name="Groups").click()
    expect(page.get_by_role("heading", name="Groups", exact=True)).to_be_visible()
    page.wait_for_load_state("networkidle")
    expect(page.get_by_role("cell", name="Newsletter", exact=True).filter(visible=True)).to_be_visible()
    page.get_by_role("button", exact=True, name="New group").click()
    page.fill("#g-name", "Diwali 2026"); page.get_by_role("button", exact=True, name="Create group").click()
    expect(page.get_by_role("cell", name="Diwali 2026", exact=True).filter(visible=True)).to_be_visible()
    shot(page, "11-groups")
    page.get_by_role("link", name="Custom fields").click()
    expect(page.get_by_role("heading", name="Custom fields", exact=True)).to_be_visible()
    page.get_by_role("button", exact=True, name="New field").click()
    page.fill("#f-label", "Customer since"); page.locator("#f-type").select_option("date")
    page.get_by_role("button", exact=True, name="Add field").click()
    expect(page.get_by_text("{customer_since}").filter(visible=True)).to_be_visible()
    shot(page, "12-custom-fields")
    page.get_by_role("link", name="Team").click()
    expect(page.get_by_role("heading", name="Team", exact=True)).to_be_visible()
    page.get_by_role("button", exact=True, name="Add teammate").click()
    page.fill("#t-name", "Ravi Staff"); page.fill("#t-email", "ravi@acme.test"); page.fill("#t-pw", "StaffPass2026")
    page.locator("dialog[open]").get_by_role("button", exact=True, name="Add teammate").click()
    expect(page.get_by_text("ravi@acme.test").filter(visible=True)).to_be_visible()
    shot(page, "13-team")

    # Staff permissions in the UI
    page.get_by_role("button", name=re.compile("Asha Verma")).click()
    page.get_by_role("button", exact=True, name="Sign out").click()
    expect(page).to_have_url(re.compile("/login"))
    page.fill("#email", "ravi@acme.test"); page.fill("#password", "StaffPass2026"); page.click("button[type=submit]")
    expect(page.get_by_role("heading", name="Hi Ravi")).to_be_visible()
    page.get_by_role("navigation", name="Main").get_by_role("link", name="Contacts", exact=True).click()
    expect(page.get_by_role("button", exact=True, name="Add contact")).to_be_visible()
    expect(page.get_by_role("button", exact=True, name="Import")).to_have_count(0)
    expect(page.get_by_role("button", exact=True, name="Export")).to_have_count(0)
    expect(page.locator("tbody").get_by_role("button", exact=True, name="Delete")).to_have_count(0)
    shot(page, "14-staff-view")

    # Mobile
    m = b.new_context(viewport={"width": 390, "height": 844}, storage_state=ctx.storage_state())
    mp = m.new_page()
    mp.on("pageerror", lambda e: errors.append(f"mobile pageerror: {e}"))
    mp.goto(f"{BASE}/contacts")
    expect(mp.get_by_role("button", exact=True, name="Piper Reeves")).to_be_visible()
    mp.screenshot(path=f"{OUT}/15-mobile-contacts.png")
    mp.get_by_role("button", exact=True, name="Open menu").click()
    mp.wait_for_timeout(300)
    mp.screenshot(path=f"{OUT}/16-mobile-menu.png")
    overflow = mp.evaluate("document.documentElement.scrollWidth > window.innerWidth")
    if overflow: errors.append("mobile: horizontal page overflow")

    # Register page
    np_ = b.new_page(viewport={"width": 1440, "height": 900})
    np_.goto(f"{BASE}/register")
    np_.screenshot(path=f"{OUT}/00-register.png")
    b.close()

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