"""Shared streaming HTTP downloader with headless browser fallback."""

from pathlib import Path

import httpx

from huntpdf.browser import fetch_pdf_browser_sync
from huntpdf.errors import DownloadFailed, PDFNotFound

_USER_AGENT = "huntpdf/0.1.0"
_TIMEOUT = 60.0
_VALID_CONTENT_TYPES = ("application/pdf", "application/octet-stream")


def download_pdf(url: str, output: Path) -> Path:
    """Download a PDF from a URL, falling back to a headless browser on failure.

    Args:
        url: Direct URL to the PDF resource.
        output: Destination file path.

    Returns:
        The output path on success.

    Raises:
        PDFNotFound: If the server returns 404.
        DownloadFailed: If both httpx and browser fallback fail.
    """
    try:
        return _download_httpx(url, output)
    except PDFNotFound:
        raise
    except (httpx.HTTPStatusError, DownloadFailed):
        pass

    try:
        return fetch_pdf_browser_sync(url, output)
    except Exception as exc:
        raise DownloadFailed(f"All download methods failed for {url}") from exc


def _download_httpx(url: str, output: Path) -> Path:
    headers = {"User-Agent": _USER_AGENT}
    with httpx.Client(timeout=_TIMEOUT, follow_redirects=True) as client:
        with client.stream("GET", url, headers=headers) as response:
            if response.status_code == 404:
                raise PDFNotFound(f"404 Not Found: {url}")
            response.raise_for_status()

            content_type = response.headers.get("content-type", "")
            if not any(ct in content_type for ct in _VALID_CONTENT_TYPES):
                raise DownloadFailed(
                    f"Unexpected content-type: {content_type}"
                )

            output.parent.mkdir(parents=True, exist_ok=True)
            with open(output, "wb", buffering=0) as f:
                for chunk in response.iter_bytes():
                    f.write(chunk)

    return output
