"""
Comprehensive E2E flow tests using Playwright.

Covers all major user flows: public pages, planner, auth, directory, quote wizard,
billing, supplier dashboard, and cross-cutting checks (translations, footer, language switcher).

Skipped by default (requires `playwright install chromium`).
Run explicitly with:
    uv run pytest -m visual tests/test_e2e_flows.py -v
"""
import pytest
from playwright.sync_api import expect

pytestmark = pytest.mark.visual


@pytest.fixture
def page(browser):
    """Wide desktop page for E2E tests (1440px for sidebar tests)."""
    pg = browser.new_page(viewport={"width": 1440, "height": 900})
    yield pg
    pg.close()


def dev_login(page, base, email="test@example.com"):
    """Instantly authenticate via dev-login endpoint."""
    page.goto(f"{base}/auth/dev-login?email={email}")
    page.wait_for_load_state("networkidle")


# =============================================================================
# A. Public Pages — smoke test every public GET returns 200
# =============================================================================

def test_root_redirects_to_lang(live_server, page):
    """GET / should redirect to /<lang>/."""
    resp = page.goto(live_server + "/")
    assert resp.ok, f"/ returned {resp.status}"
    assert "/en/" in page.url or "/de/" in page.url, f"No lang in URL: {page.url}"


@pytest.mark.parametrize("path", [
    "/en/",
    "/de/",
    "/en/features",
    "/en/terms",
    "/en/privacy",
    "/en/about",
    "/en/imprint",
    "/en/suppliers",
    "/de/features",
    "/de/about",
    "/de/suppliers",
])
def test_public_page_200(live_server, page, path):
    """Every public page should return 200 and contain meaningful content."""
    resp = page.goto(live_server + path)
    assert resp.ok, f"{path} returned {resp.status}"
    heading = page.locator("h1, h2").first
    expect(heading).to_be_visible()


def test_robots_txt(live_server, page):
    resp = page.goto(live_server + "/robots.txt")
    assert resp.ok
    assert "User-agent" in page.content()


def test_sitemap_xml(live_server, page):
    resp = page.goto(live_server + "/sitemap.xml")
    assert resp.ok
    assert "<urlset" in page.content() or "<sitemapindex" in page.content()


def test_health_endpoint(live_server, page):
    resp = page.goto(live_server + "/health")
    assert resp.ok


# =============================================================================
# B. Planner Flow
# =============================================================================

def test_planner_en_loads(live_server, page):
    """Planner page renders wizard and tab bar."""
    resp = page.goto(live_server + "/en/planner/")
    assert resp.ok
    expect(page.locator("#nav")).to_be_visible()
    expect(page.locator("#planner-form")).to_be_visible()


def test_planner_de_loads(live_server, page):
    """German planner renders with German UI strings."""
    resp = page.goto(live_server + "/de/planner/")
    assert resp.ok
    content = page.content()
    assert "Investition" in content or "Annahmen" in content or "Anlage" in content


def test_planner_calculate_htmx(live_server, page):
    """Clicking a result tab fires HTMX and shows the results panel."""
    page.goto(live_server + "/en/planner/")
    page.wait_for_load_state("networkidle")

    capex_btn = page.locator("button[data-tab='capex'], [data-tab='capex']").first
    capex_btn.click()
    page.wait_for_timeout(1000)

    tab_content = page.locator("#tab-content")
    expect(tab_content).to_be_visible()
    assert len(tab_content.inner_html()) > 100


def test_planner_tab_switching(live_server, page):
    """Clicking all result tabs renders different content each time."""
    page.goto(live_server + "/en/planner/")
    page.wait_for_load_state("networkidle")

    tabs = ["capex", "operating", "cashflow", "returns"]
    seen_contents = set()

    for tab_id in tabs:
        btn = page.locator(f"button[data-tab='{tab_id}'], [data-tab='{tab_id}']").first
        if btn.count() == 0:
            btn = page.get_by_role("button", name=tab_id, exact=False).first
        btn.click()
        page.wait_for_timeout(600)
        html = page.locator("#tab-content").inner_html()
        seen_contents.add(html[:100])

    assert len(seen_contents) >= 3, "Tab content didn't change across tabs"


def test_planner_chart_data_present(live_server, page):
    """Result tabs embed chart data as JSON script tags."""
    page.goto(live_server + "/en/planner/")
    page.wait_for_load_state("networkidle")

    chart_scripts = page.locator("script[type='application/json']")
    assert chart_scripts.count() >= 1, "No chart JSON script tags found"


def test_planner_quote_sidebar_visible_wide(live_server, browser):
    """Quote sidebar should be visible on wide viewport (>1400px)."""
    pg = browser.new_page(viewport={"width": 1600, "height": 900})
    pg.goto(live_server + "/en/planner/")
    pg.wait_for_load_state("networkidle")

    sidebar = pg.locator(".quote-sidebar")
    if sidebar.count() > 0:
        display = pg.evaluate(
            "getComputedStyle(document.querySelector('.quote-sidebar')).display"
        )
        assert display != "none", f"Quote sidebar hidden on wide viewport: display={display}"
    pg.close()


# =============================================================================
# C. Auth Flow
# =============================================================================

def test_login_page_loads(live_server, page):
    resp = page.goto(live_server + "/auth/login")
    assert resp.ok
    expect(page.locator("form").first).to_be_visible()
    expect(page.locator("input[type='email']")).to_be_visible()


def test_signup_page_loads(live_server, page):
    resp = page.goto(live_server + "/auth/signup")
    assert resp.ok
    expect(page.locator("form").first).to_be_visible()


def test_dev_login_redirects_to_dashboard(live_server, page):
    """Dev login should create session and redirect to dashboard."""
    page.goto(live_server + "/auth/dev-login?email=devtest@example.com")
    page.wait_for_load_state("networkidle")
    assert "/dashboard" in page.url, f"Expected dashboard redirect, got: {page.url}"


def test_authenticated_dashboard_loads(live_server, page):
    """After dev-login, dashboard should be accessible."""
    dev_login(page, live_server, "dash@example.com")
    assert "/dashboard" in page.url
    resp_status = page.evaluate("() => document.readyState")
    assert resp_status == "complete"


def test_dashboard_quote_link_goes_to_wizard(live_server, page):
    """Dashboard 'request quote' button should link to the quote wizard."""
    dev_login(page, live_server, "dashquote@example.com")
    href = page.locator("a", has_text="Quote").first.get_attribute("href")
    assert "/leads/quote" in href, f"Expected quote wizard link, got: {href}"
    assert "suppliers" not in href, f"Link should not point to suppliers page: {href}"


def test_unauthenticated_dashboard_redirects(live_server, page):
    """Without auth, /dashboard/ should redirect to login."""
    page.goto(live_server + "/dashboard/", wait_until="networkidle")
    assert "login" in page.url or "auth" in page.url, (
        f"Expected redirect to login, got: {page.url}"
    )


def test_magic_link_sent_page(live_server, page):
    """Magic link sent page renders with the email address shown."""
    resp = page.goto(live_server + "/auth/magic-link-sent?email=test@example.com")
    assert resp.ok
    expect(page.get_by_text("test@example.com")).to_be_visible()


# =============================================================================
# D. Directory Flow
# =============================================================================

def test_directory_en_loads(live_server, page):
    resp = page.goto(live_server + "/en/directory/")
    assert resp.ok
    expect(page.locator("h1, h2").first).to_be_visible()


def test_directory_de_loads(live_server, page):
    resp = page.goto(live_server + "/de/directory/")
    assert resp.ok
    content = page.content()
    assert "Lieferanten" in content or "Anbieter" in content or "Kategorie" in content or resp.ok


def test_directory_search_htmx(live_server, page):
    """Typing in directory search fires HTMX and returns results partial."""
    page.goto(live_server + "/en/directory/")
    page.wait_for_load_state("networkidle")

    search = page.locator("input[type='search'], input[name='q'], input[type='text']").first
    if search.count() == 0:
        pytest.skip("No search input found")

    search.fill("padel")
    page.wait_for_timeout(600)
    results = page.locator("#supplier-results, #results, [id*='result']").first
    expect(results).to_be_visible()


# =============================================================================
# E. Quote Flow (key steps)
# =============================================================================

def test_quote_step1_loads(live_server, page):
    """Quote wizard step 1 renders the form."""
    resp = page.goto(live_server + "/en/leads/quote")
    assert resp.ok
    expect(page.locator("form").first).to_be_visible()


def test_quote_step1_de_loads(live_server, page):
    resp = page.goto(live_server + "/de/leads/quote")
    assert resp.ok
    content = page.content()
    assert "Anlage" in content or "Platz" in content or "Projekt" in content or resp.ok


def test_quote_verify_url_includes_lang(live_server, page):
    """Verify the leads/verify route exists at /<lang>/leads/verify."""
    resp = page.goto(live_server + "/en/leads/verify?token=invalid")
    assert resp.status != 404, "Verify endpoint returned 404 — lang prefix missing?"


# =============================================================================
# F. Authenticated Flows (planner scenarios, leads forms)
# =============================================================================

def test_authenticated_planner_loads(live_server, page):
    """Authenticated user can access the planner."""
    dev_login(page, live_server, "planneruser@example.com")
    resp = page.goto(live_server + "/en/planner/")
    assert resp.ok
    expect(page.locator("#planner-form")).to_be_visible()


def test_planner_scenarios_list(live_server, page):
    """Authenticated user can access scenarios list."""
    dev_login(page, live_server, "scenuser@example.com")
    resp = page.goto(live_server + "/en/planner/scenarios")
    assert resp.ok


# =============================================================================
# G. Cross-Cutting Checks
# =============================================================================

def test_footer_present_on_public_pages(live_server, page):
    """Footer should be present on all public pages."""
    for path in ["/en/", "/en/features", "/en/about"]:
        page.goto(live_server + path)
        expect(page.locator("footer")).to_be_visible()


def test_footer_has_four_column_layout(live_server, page):
    """Footer grid should have 4 link columns."""
    page.goto(live_server + "/en/")
    page.wait_for_load_state("networkidle")

    footer_cols = page.evaluate("""
        (() => {
            const footer = document.querySelector('footer');
            if (!footer) return 0;
            const grid = footer.querySelector('[class*="grid"]');
            if (!grid) return 0;
            return grid.children.length;
        })()
    """)
    assert footer_cols >= 4, f"Expected 4 footer columns, found {footer_cols}"


def test_language_switcher_en_to_de(live_server, page):
    """Language switcher should navigate from /en/ to /de/."""
    page.goto(live_server + "/en/")
    page.wait_for_load_state("networkidle")

    de_link = page.locator("a[href='/de/']").first
    if de_link.count() == 0:
        pytest.skip("No DE language switcher link found")

    href = de_link.get_attribute("href")
    assert href and "/de" in href, f"DE link has unexpected href: {href}"

    page.goto(live_server + "/de/")
    page.wait_for_load_state("networkidle")
    assert "/de/" in page.url, f"Language switch failed: {page.url}"


def test_no_missing_translations_en(live_server, page):
    """EN pages should not contain untranslated markers."""
    for path in ["/en/", "/en/features", "/en/about"]:
        page.goto(live_server + path)
        content = page.locator("body").inner_text()
        assert "t.auth_" not in content, f"Untranslated key in {path}"
        assert "{{" not in content, f"Jinja template not rendered in {path}"


def test_no_missing_translations_de(live_server, page):
    """DE pages should contain German text, not raw English keys."""
    page.goto(live_server + "/de/")
    content = page.locator("body").inner_text()
    assert "{{" not in content, "Jinja template not rendered in /de/"
    assert "t.auth_" not in content, "Untranslated key in /de/"


def test_auth_login_page_german(live_server, page):
    """Auth login should render in German when lang cookie is 'de'."""
    page.context.add_cookies([{
        "name": "lang", "value": "de",
        "domain": "127.0.0.1", "path": "/"
    }])
    page.goto(live_server + "/auth/login")
    content = page.content()
    assert "Anmelden" in content or "E-Mail" in content or "Weiter" in content


def test_404_for_nonexistent_page(live_server, page):
    """Non-existent pages should return 404."""
    resp = page.goto(live_server + "/en/this-page-does-not-exist-xyz")
    assert resp.status == 404, f"Expected 404, got {resp.status}"


def test_legacy_redirect_terms(live_server, page):
    """Legacy /terms should redirect to /en/terms."""
    resp = page.goto(live_server + "/terms")
    assert resp.ok or resp.status in (301, 302)


# =============================================================================
# H. Markets
# =============================================================================

def test_markets_hub_loads(live_server, page):
    """Markets hub should load normally."""
    resp = page.goto(live_server + "/en/markets")
    assert resp.ok
    expect(page.locator("h1, h2").first).to_be_visible()


def test_markets_results_partial_loads(live_server, page):
    """Markets results HTMX partial should return 200."""
    resp = page.goto(live_server + "/en/markets/results")
    assert resp.ok


# =============================================================================
# I. Tooltip Presence
# =============================================================================

def test_planner_tooltips_present(live_server, page):
    """Result tabs should contain tooltip spans for complex financial terms."""
    page.goto(live_server + "/en/planner/")
    page.wait_for_load_state("networkidle")

    returns_btn = page.locator("button[data-tab='returns'], [data-tab='returns']").first
    if returns_btn.count() > 0:
        returns_btn.click()
        page.wait_for_timeout(600)

    ti_spans = page.locator(".ti")
    assert ti_spans.count() >= 1, "No tooltip spans (.ti) found on results tab"


# =============================================================================
# J. Pricing Page
# =============================================================================

def test_pricing_page_loads_en(live_server, page):
    """Pricing page renders in English."""
    resp = page.goto(live_server + "/billing/pricing")
    assert resp.ok, f"/billing/pricing returned {resp.status}"
    expect(page.locator("h1").first).to_be_visible()


def test_pricing_page_loads_de(live_server, page):
    """Pricing page renders in German when lang cookie is set."""
    page.context.add_cookies([{
        "name": "lang", "value": "de",
        "domain": "127.0.0.1", "path": "/"
    }])
    resp = page.goto(live_server + "/billing/pricing")
    assert resp.ok, f"/billing/pricing returned {resp.status}"
    expect(page.locator("h1").first).to_be_visible()


def test_pricing_page_has_plan_cards(live_server, page):
    """Pricing page shows at least 2 plan cards with CTAs."""
    page.goto(live_server + "/billing/pricing")
    page.wait_for_load_state("networkidle")
    cards = page.locator(".card-header")
    assert cards.count() >= 2, f"Expected >=2 plan cards, found {cards.count()}"
    ctas = page.locator("a.btn, a.btn-outline")
    assert ctas.count() >= 2, f"Expected >=2 CTAs, found {ctas.count()}"


def test_pricing_page_no_auth_required(live_server, page):
    """Pricing page is accessible without authentication."""
    resp = page.goto(live_server + "/billing/pricing")
    assert resp.ok
    assert "login" not in page.url and "auth" not in page.url


# =============================================================================
# K. Checkout Success
# =============================================================================

def test_checkout_success_requires_auth(live_server, page):
    """Checkout success page redirects unauthenticated users to login."""
    page.goto(live_server + "/billing/success", wait_until="networkidle")
    assert "login" in page.url or "auth" in page.url, (
        f"Expected redirect to login, got: {page.url}"
    )


def test_checkout_success_renders_for_authed_user(live_server, page):
    """Checkout success page renders for authenticated user."""
    dev_login(page, live_server, "checkout@example.com")
    resp = page.goto(live_server + "/billing/success")
    assert resp.ok
    expect(page.locator("h1").first).to_be_visible()
    expect(page.locator("a.btn").first).to_be_visible()


# =============================================================================
# L. Supplier Signup Wizard
# =============================================================================

def test_supplier_signup_step1_loads(live_server, page):
    """Supplier signup wizard step 1 renders."""
    resp = page.goto(live_server + "/en/suppliers/signup")
    assert resp.ok, f"/en/suppliers/signup returned {resp.status}"
    page.wait_for_load_state("networkidle")
    expect(page.locator("[data-step='1']").first).to_be_visible()


def test_supplier_signup_step1_has_plan_cards(live_server, page):
    """Step 1 shows plan cards for selecting a tier."""
    page.goto(live_server + "/en/suppliers/signup")
    page.wait_for_load_state("networkidle")
    plan_cards = page.locator(".s-plan-card")
    assert plan_cards.count() >= 2, (
        f"Expected >=2 plan cards, found {plan_cards.count()}"
    )
    expect(page.locator(".s-btn-next").first).to_be_visible()


def test_supplier_signup_step1_de_loads(live_server, page):
    """German variant of supplier signup wizard loads."""
    resp = page.goto(live_server + "/de/suppliers/signup")
    assert resp.ok, f"/de/suppliers/signup returned {resp.status}"
    page.wait_for_load_state("networkidle")
    expect(page.locator("[data-step='1']").first).to_be_visible()


def test_supplier_signup_success_page_loads(live_server, page):
    """Supplier signup success page renders."""
    resp = page.goto(live_server + "/en/suppliers/signup/success")
    assert resp.ok, f"signup success returned {resp.status}"
    expect(page.locator("h1, h2").first).to_be_visible()


# =============================================================================
# M. Supplier Dashboard (seeded supplier data)
# =============================================================================

def test_supplier_dashboard_loads(live_server, page):
    """Dashboard loads for authenticated supplier."""
    dev_login(page, live_server, "supplier@test.com")
    resp = page.goto(live_server + "/en/suppliers/dashboard")
    assert resp.ok, f"dashboard returned {resp.status}"
    expect(page.locator(".dash").first).to_be_visible()
    expect(page.locator(".dash-sidebar__name").first).to_be_visible()


def test_supplier_dashboard_overview_tab(live_server, page):
    """Overview tab renders with stats grid."""
    dev_login(page, live_server, "supplier@test.com")
    page.goto(live_server + "/en/suppliers/dashboard")
    page.wait_for_load_state("networkidle")
    page.wait_for_timeout(1000)
    stats = page.locator(".ov-stat")
    assert stats.count() >= 2, f"Expected >=2 stat cards, found {stats.count()}"


def test_supplier_dashboard_boosts_tab(live_server, page):
    """Boosts tab renders with boost options."""
    dev_login(page, live_server, "supplier@test.com")
    resp = page.goto(live_server + "/en/suppliers/dashboard/boosts")
    assert resp.ok, f"boosts tab returned {resp.status}"


def test_supplier_dashboard_boosts_has_credit_packs(live_server, page):
    """Boosts tab shows credit pack purchase options."""
    dev_login(page, live_server, "supplier@test.com")
    page.goto(live_server + "/en/suppliers/dashboard/boosts")
    page.wait_for_load_state("networkidle")
    content = page.content()
    assert "25" in content or "50" in content or "100" in content, (
        "No credit pack amounts found on boosts page"
    )


def test_supplier_dashboard_listing_tab(live_server, page):
    """Listing tab renders for authenticated supplier."""
    dev_login(page, live_server, "supplier@test.com")
    resp = page.goto(live_server + "/en/suppliers/dashboard/listing")
    assert resp.ok, f"listing tab returned {resp.status}"


def test_supplier_dashboard_leads_tab(live_server, page):
    """Leads tab renders for pro-tier supplier."""
    dev_login(page, live_server, "supplier@test.com")
    resp = page.goto(live_server + "/en/suppliers/dashboard/leads")
    assert resp.ok, f"leads tab returned {resp.status}"


# =============================================================================
# N. Business Plan Export
# =============================================================================

def test_export_page_requires_auth(live_server, page):
    """Export page redirects unauthenticated users to login."""
    page.goto(live_server + "/en/planner/export", wait_until="networkidle")
    assert "login" in page.url or "auth" in page.url, (
        f"Expected redirect to login, got: {page.url}"
    )


def test_export_page_loads_for_authed_user(live_server, page):
    """Export page renders for authenticated user with form."""
    dev_login(page, live_server, "export@example.com")
    resp = page.goto(live_server + "/en/planner/export")
    assert resp.ok, f"export page returned {resp.status}"
    expect(page.locator("h1").first).to_be_visible()
    expect(page.locator("#export-form").first).to_be_visible()
    expect(page.locator("#export-buy-btn").first).to_be_visible()
