"""HTTP-клиент для раздела «Изъятие для муниципальных нужд» екатеринбург.рф (#1062).

Источник: https://xn--80acgfbsl1azdqr.xn--p1ai/дляработы/гиз/градостроительство/изъятие
Страница содержит список ссылок /file/<md5hash> на PDF-сканы «Сообщений о планируемом
изъятии…» под муниципальные нужды.

TLS: екатеринбург.рф использует российский УЦ → verify=False (как в ekb_geoportal_client.py,
issue #242). Прод-IP имеет доступ к домену (мы уже скрапим РНС/КРТ с того же домена).
"""

from __future__ import annotations

import logging
import re
import urllib.parse

import httpx
from bs4 import BeautifulSoup

logger = logging.getLogger(__name__)

# Punycode URL раздела изъятия (ekb.rf → xn--80acgfbsl1azdqr.xn--p1ai).
_IZYATIE_URL = (
    "https://xn--80acgfbsl1azdqr.xn--p1ai"
    "/%D0%B4%D0%BB%D1%8F%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B"
    "/%D0%B3%D0%B8%D0%B7"
    "/%D0%B3%D1%80%D0%B0%D0%B4%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE"
    "/%D0%B8%D0%B7%D1%8A%D1%8F%D1%82%D0%B8%D0%B5"
)
_BASE_URL = "https://xn--80acgfbsl1azdqr.xn--p1ai"

# Браузерный User-Agent — домен отдаёт robots.txt только для ботов.
_UA = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/124.0.0.0 Safari/537.36"
)

# Паттерн file-ссылки — /file/<md5hash> (32 hex-символа).
_RE_FILE_HREF = re.compile(r"^/file/[0-9a-f]{32}$", re.IGNORECASE)

# Ключевые слова для отфильтровки ссылок раздела изъятия.
# Берём все /file/-ссылки на странице: раздел посвящён только изъятию, других PDF там нет.
_IZYATIE_KEYWORDS = re.compile(
    r"изъят|планируемом|сообщени|муниципальн|татищева|базовый|комсомольск|"
    r"энергостроит|павлодарск|иркутск|щербак|шаумян",
    re.IGNORECASE | re.UNICODE,
)


def list_izyatie_documents(url: str = _IZYATIE_URL) -> list[dict[str, str]]:
    """Получает список PDF-документов об изъятии с раздела екатеринбург.рф.

    Парсит страницу раздела и возвращает все /file/<hash>-ссылки.
    Если страница вернула пустой список — логирует предупреждение (не падает).

    Args:
        url: URL раздела изъятия (по умолчанию prod-URL).

    Returns:
        Список словарей {'title': str, 'url': str} — название ссылки и абсолютный URL PDF.
        Пустой список при сетевой ошибке или отсутствии ссылок.
    """
    try:
        with httpx.Client(
            timeout=30.0,
            verify=False,
            follow_redirects=True,
            headers={"User-Agent": _UA},
        ) as client:
            resp = client.get(url)
            resp.raise_for_status()
            html = resp.text
    except Exception as exc:
        logger.error("list_izyatie_documents: не удалось загрузить страницу %s: %s", url, exc)
        return []

    soup = BeautifulSoup(html, "html.parser")
    docs: list[dict[str, str]] = []

    for a_tag in soup.find_all("a", href=True):
        href: str = a_tag["href"]
        # Берём только /file/<hash>-ссылки.
        if not _RE_FILE_HREF.match(href):
            continue
        # Заголовок: текст якоря → title-атрибут → href как последний фолбэк.
        title: str = a_tag.get_text(strip=True) or a_tag.get("title") or href
        absolute_url = urllib.parse.urljoin(_BASE_URL, href)
        docs.append({"title": title, "url": absolute_url})

    if not docs:
        logger.warning(
            "list_izyatie_documents: не найдено /file/-ссылок на странице %s "
            "(возможно, изменилась структура HTML или все документы удалены)",
            url,
        )
    else:
        logger.info("list_izyatie_documents: найдено %d документов на %s", len(docs), url)

    return docs


def fetch_pdf(url: str) -> bytes:
    """Загружает PDF по URL с екатеринбург.рф.

    Args:
        url: абсолютный URL PDF-файла (/file/<hash>).

    Returns:
        Сырые байты PDF.

    Raises:
        httpx.HTTPError: при ошибке сети или не-200 статусе.
    """
    with httpx.Client(
        timeout=60.0,
        verify=False,
        follow_redirects=True,
        headers={"User-Agent": _UA},
    ) as client:
        resp = client.get(url)
        resp.raise_for_status()
        return resp.content


__all__ = ["fetch_pdf", "list_izyatie_documents"]
