from __future__ import annotations

import logging
from dataclasses import dataclass
from typing import Any, Dict, Optional

from bs4 import BeautifulSoup

try:
    from newspaper import Article  # type: ignore
    NEWSPAPER_AVAILABLE = True
except Exception:
    NEWSPAPER_AVAILABLE = False

from langdetect import detect as detect_lang  # lightweight heuristic

logger = logging.getLogger(__name__)


@dataclass
class ExtractedDocument:
    url: str
    title: str
    text: str
    author: Optional[str]
    date: Optional[str]
    canonical_url: Optional[str]


def _fallback_bs4_extract(html: str) -> Dict[str, Optional[str]]:
    soup = BeautifulSoup(html or "", "html.parser")
    title = (soup.title.string or "").strip() if soup.title else ""
    # crude text extraction
    for tag in soup(["script", "style", "noscript"]):
        tag.decompose()
    text = " ".join(soup.get_text(separator=" ").split())[:200000]
    author = None
    canonical = None
    date = None
    # simple meta lookups
    can = soup.find("link", rel="canonical")
    if can and can.has_attr("href"):
        canonical = can["href"]
    meta_author = soup.find("meta", attrs={"name": "author"})
    if meta_author and meta_author.has_attr("content"):
        author = meta_author["content"]
    meta_date = soup.find("meta", attrs={"property": "article:published_time"})
    if meta_date and meta_date.has_attr("content"):
        date = meta_date["content"]
    return {"title": title, "text": text, "author": author, "canonical_url": canonical, "date": date}


def extract_article(url: str, html: str) -> ExtractedDocument:
    if NEWSPAPER_AVAILABLE:
        try:
            art = Article(url)
            art.set_html(html)
            art.parse()
            title = (art.title or "").strip()
            text = (art.text or "").strip()
            author = ", ".join(art.authors) if getattr(art, "authors", None) else None
            date = art.publish_date.isoformat() if getattr(art, "publish_date", None) else None
            canonical = getattr(art, "canonical_link", None)
            if text:
                return ExtractedDocument(url=url, title=title, text=text, author=author, date=date, canonical_url=canonical)
        except Exception as e:
            logger.warning("newspaper3k failed, falling back: %s", e)
    meta = _fallback_bs4_extract(html)
    return ExtractedDocument(url=url, title=meta["title"] or "", text=meta["text"] or "", author=meta["author"], date=meta["date"], canonical_url=meta["canonical_url"]) 


def detect_language(text: str) -> Optional[str]:
    try:
        return detect_lang(text[:5000]) if text else None
    except Exception:
        return None


