from __future__ import annotations
import ssl as _ssl
import warnings

import httpx
from bs4 import BeautifulSoup
from ..models import DocumentContent, TextSegment


def _is_ssl_error(exc: Exception) -> bool:
    msg = str(exc).lower()
    if "ssl" in msg or "certificate" in msg or "cert" in msg:
        return True
    cause = getattr(exc, "__cause__", None)
    return isinstance(cause, _ssl.SSLError)


async def parse_web(
    url: str,
    verify_ssl: bool = True,
) -> tuple[str, DocumentContent]:
    """Fetch a URL and extract its text content.

    Parameters
    ----------
    url:
        The URL to fetch.
    verify_ssl:
        Whether to verify the server's TLS certificate (default ``True``).
        Set to ``False`` for sites that use non-standard CA certificates
        (e.g. OASIS portals, some utility FERC compliance pages).
        If ``True`` and an SSL error is encountered, the request is
        automatically retried without verification and a warning is emitted.
    """
    async def _fetch(verify: bool) -> httpx.Response:
        async with httpx.AsyncClient(
            follow_redirects=True, timeout=30.0, verify=verify
        ) as client:
            return await client.get(url)

    try:
        response = await _fetch(verify_ssl)
    except Exception as exc:
        if verify_ssl and _is_ssl_error(exc):
            warnings.warn(
                f"SSL verification failed for {url}; retrying without certificate "
                "verification. Pass verify_ssl=False to suppress this warning.",
                stacklevel=2,
            )
            response = await _fetch(False)
        else:
            raise

    response.raise_for_status()

    soup = BeautifulSoup(response.text, "html.parser")

    title_tag = soup.find("title")
    title = title_tag.get_text().strip() if title_tag else url

    for tag in soup(["script", "style", "noscript", "nav", "footer", "header"]):
        tag.decompose()

    text_parts: list[str] = []
    for el in soup.find_all(["p", "h1", "h2", "h3", "h4", "h5", "h6", "li", "td"]):
        text = el.get_text().strip()
        if text:
            text_parts.append(text)

    segments: list[TextSegment] = []
    raw_text = ""
    for text in text_parts:
        segments.append(TextSegment(text=text, charOffset=len(raw_text)))
        raw_text += text + "\n\n"

    return title, DocumentContent(rawText=raw_text.rstrip(), segments=segments)
