"""Fetch and extract content from URLs, files, or raw text for summarization."""

import re
from pathlib import Path

import httpx
import markdownify

MAX_CONTENT = 50_000


def _detect_source_type(source: str) -> str:
    """Detect whether source is a URL, file path, or raw text."""
    s = source.strip()
    if s.startswith(("http://", "https://")):
        return "url"
    if s.startswith("/") or s.startswith("~"):
        return "file"
    # Check if it looks like a relative path that exists
    if not s.startswith(" ") and len(s) < 500 and Path(s).is_file():
        return "file"
    return "text"


def _clean_text(text: str) -> str:
    """Remove excessive whitespace and blank lines."""
    text = re.sub(r"\n{3,}", "\n\n", text)
    text = re.sub(r"[ \t]+", " ", text)
    return text.strip()


async def _fetch_url(client: httpx.AsyncClient, url: str) -> tuple[str, str]:
    """Fetch URL and convert to text. Returns (title, content)."""
    resp = await client.get(url, follow_redirects=True)
    resp.raise_for_status()
    html = resp.text

    # Extract title
    title = ""
    title_match = re.search(r"<title[^>]*>(.*?)</title>", html, re.IGNORECASE | re.DOTALL)
    if title_match:
        title = title_match.group(1).strip()

    # Convert to markdown (cleaner than raw HTML)
    content = markdownify.markdownify(html, strip=["img", "script", "style", "nav", "footer", "header"])
    return title, _clean_text(content)


def _read_file(file_path: str) -> tuple[str, str]:
    """Read a local file. Returns (filename, content)."""
    path = Path(file_path).expanduser()
    if not path.exists():
        raise ValueError(f"File not found: {file_path}")
    if not path.is_file():
        raise ValueError(f"Not a file: {file_path}")

    # Size check
    size_mb = path.stat().st_size / (1024 * 1024)
    if size_mb > 10:
        raise ValueError(f"File too large ({size_mb:.1f} MB). Max 10 MB.")

    try:
        content = path.read_text(encoding="utf-8")
    except UnicodeDecodeError:
        raise ValueError(f"Cannot read binary file: {file_path}. Use read_pdf for PDFs.")

    return path.name, _clean_text(content)


async def handler(params: dict) -> dict:
    """Fetch and extract content from a source for summarization."""
    source = params["source"]
    max_length = min(int(params.get("max_length") or MAX_CONTENT), MAX_CONTENT)

    source_type = _detect_source_type(source)
    title = ""
    content = ""

    if source_type == "url":
        async with httpx.AsyncClient(timeout=30) as client:
            title, content = await _fetch_url(client, source.strip())
    elif source_type == "file":
        title, content = _read_file(source.strip())
    else:
        title = "Raw text"
        content = _clean_text(source)

    truncated = len(content) > max_length
    if truncated:
        content = content[:max_length] + "\n\n... (truncated)"

    return {
        "source_type": source_type,
        "title": title,
        "content": content,
        "content_length": len(content),
        "truncated": truncated,
    }
