from __future__ import annotations

import time
import requests

from .errors import ForvoBlockedError
_REAL_CONTENT_MARKER = "_AUDIO_HTTP_HOST"


def make_session() -> requests.Session:
    """
    Make a more browser-like session to avoid 403s.
    """
    s = requests.Session()
    s.headers.update(
        {
            "User-Agent": (
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
                "AppleWebKit/537.36 (KHTML, like Gecko) "
                "Chrome/122.0.0.0 Safari/537.36"
            ),
            "Accept": (
                "text/html,application/xhtml+xml,application/xml;"
                "q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"
            ),
            "Accept-Language": "en-US,en;q=0.9",
            "Accept-Encoding": "gzip, deflate, br",
            "Connection": "keep-alive",
            "Upgrade-Insecure-Requests": "1",
        }
    )
    return s


def fetch_html_requests(url: str, session: requests.Session) -> str:
    """
    Requests-based fetch with:
    - warm-up homepage (cookies)
    - referer header
    """
    homepage = "https://forvo.com/"
    try:
        session.get(homepage, timeout=20)
    except requests.RequestException:
        pass

    headers = {"Referer": homepage}
    r = session.get(url, headers=headers, timeout=30)

    if r.status_code == 403:
        raise ForvoBlockedError(
            "HTTP 403 Forbidden. Forvo is blocking non-browser requests.\n"
            "Try:\n"
            "  1) --use-playwright (recommended)\n"
            "  2) run from a different network/IP\n"
            "  3) ensure you can open the URL in a normal browser\n"
        )

    r.raise_for_status()
    return r.text


def _wait_for_real_content(page, timeout_ms: int = 60_000, poll_interval_ms: int = 2000) -> str:
    """
    Wait until the page shows real Forvo content (past Cloudflare/security interstitial).
    Returns final HTML. Raises RuntimeError if timeout is reached before real content appears.
    """
    deadline = time.time() + (timeout_ms / 1000.0)
    while time.time() < deadline:
        html = page.content()
        if _REAL_CONTENT_MARKER in html:
            return html
        page.wait_for_timeout(min(poll_interval_ms, 2000))
    raise RuntimeError(
        "Timed out waiting for Forvo to finish security verification. "
        "Try: python3 -m scrape_forvo ... --use-playwright --headed  (visible browser often passes Cloudflare)."
    )


def fetch_html_playwright(
    url: str,
    *,
    headed: bool = False,
) -> str:
    """
    Playwright fallback: renders page like a real browser and returns final HTML.
    Requires:
      pip install playwright
      playwright install

    Waits for Cloudflare/security verification to complete before reading content.
    Use headed=True to show the browser window; Cloudflare often passes with a visible browser.
    """
    from playwright.sync_api import sync_playwright

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=not headed)
        try:
            ctx = browser.new_context(locale="en-US")
            page = ctx.new_page()
            page.goto(url, wait_until="domcontentloaded", timeout=60_000)
            page.wait_for_timeout(2000)

            try:
                html = _wait_for_real_content(page, timeout_ms=55_000, poll_interval_ms=2000)
            except RuntimeError:
                html = page.content()
                if _REAL_CONTENT_MARKER not in html:
                    raise RuntimeError(
                        "Page did not load real Forvo content (still on security verification or captcha). "
                        "Try: --use-playwright --headed  (visible browser), or run from a different network."
                    )
            return html
        finally:
            browser.close()
