from __future__ import annotations

import re
from dataclasses import dataclass
from pathlib import Path
from typing import TYPE_CHECKING
from urllib.parse import urljoin

import requests

if TYPE_CHECKING:
    pass

USER_AGENT = "ContentPipeline/1.0 (+local cron)"


@dataclass
class FetchedImage:
    path: str
    source: str  # news_og | generated
    url: str | None = None


def fetch_news_image(url: str, dest: Path, timeout: int = 15) -> FetchedImage | None:
    """Try og:image / twitter:image from the article (editorial / link-back use)."""
    if not url:
        return None
    try:
        resp = requests.get(url, timeout=timeout, headers={"User-Agent": USER_AGENT}, allow_redirects=True)
        resp.raise_for_status()
        html = resp.text[:200_000]
    except Exception:
        return None

    image_url = _extract_image_url(html, resp.url)
    if not image_url:
        return None

    try:
        img_resp = requests.get(
            image_url,
            timeout=timeout,
            headers={"User-Agent": USER_AGENT},
            allow_redirects=True,
        )
        img_resp.raise_for_status()
        ctype = (img_resp.headers.get("Content-Type") or "").split(";")[0].lower()
        if not ctype.startswith("image/"):
            return None
        if len(img_resp.content) < 5_000 or len(img_resp.content) > 8_000_000:
            return None
        ext = _ext_from_content_type(ctype)
        dest.parent.mkdir(parents=True, exist_ok=True)
        dest.write_bytes(img_resp.content)
        return FetchedImage(path=dest.name, source="news_og", url=image_url)
    except Exception:
        return None


def _extract_image_url(html: str, base_url: str) -> str | None:
    patterns = [
        r'<meta[^>]+property=["\']og:image:secure_url["\'][^>]+content=["\']([^"\']+)["\']',
        r'<meta[^>]+content=["\']([^"\']+)["\'][^>]+property=["\']og:image:secure_url["\']',
        r'<meta[^>]+property=["\']og:image["\'][^>]+content=["\']([^"\']+)["\']',
        r'<meta[^>]+content=["\']([^"\']+)["\'][^>]+property=["\']og:image["\']',
        r'<meta[^>]+name=["\']twitter:image["\'][^>]+content=["\']([^"\']+)["\']',
        r'<meta[^>]+content=["\']([^"\']+)["\'][^>]+name=["\']twitter:image["\']',
    ]
    for pat in patterns:
        m = re.search(pat, html, re.I)
        if m:
            return urljoin(base_url, m.group(1).strip())
    return None


def _ext_from_content_type(ctype: str) -> str:
    mapping = {
        "image/jpeg": ".jpg",
        "image/jpg": ".jpg",
        "image/png": ".png",
        "image/webp": ".webp",
        "image/gif": ".gif",
    }
    return mapping.get(ctype, ".jpg")
