# -*- coding: utf-8 -*-
"""
error_guard.py
===================

Lekki strażnik HTML-a: wykrywa stronki-błędy (np. CloudFront 403, WAF/CAPTCHA),
i normalizuje wynik tak, aby NIE zapisywać do bazy pełnego HTML-a błędu,
tylko kontrolną wartość "error" + meta z powodem.

API:
    is_error, reason, normalized_html = check_and_normalize_html(html, http_status=None)

- is_error: bool – czy to znany „error HTML”
- reason:   str  – krótki powód (np. "cloudfront_403")
- normalized_html: str – "error" jeśli wykryto błąd, inaczej oryginalny html
"""

from __future__ import annotations
from typing import Tuple

CLOUD_ERROR_SIGNS = (
    "the request could not be satisfied",  # CloudFront strona błędu
    "generated by cloudfront",
    "403 error",
    "request blocked.",
)

WAF_CAPTCHA_SIGNS = (
    "just a moment...",         # cloudflare/captcha
    "enable javascript",        # różne WAFy
    "access denied",            # S3/WAF
    "attention required",       # cloudflare captcha
    "bot verification",         # różne
)

# możesz rozszerzać listy powyżej w razie potrzeby


def _lc(x: str | None) -> str:
    return (x or "").lower()


def _contains_any(haystack: str, needles: tuple[str, ...]) -> bool:
    return any(n in haystack for n in needles)


def check_and_normalize_html(html: str | None, http_status: int | None = None) -> Tuple[bool, str, str]:
    """
    Zwraca: (is_error, reason, normalized_html)

    Zasada:
      - jeśli status w [403, 401, 429, 503] → "status_<code>"
      - jeśli treść HTML ma sygnatury CloudFront/WAF → "cloudfront_403" / "waf_or_captcha"
      - w przypadku błędu zwraca normalized_html = "error"
    """
    h = _lc(html)

    # 1) sprawdź statusy HTTP często oznaczające blokadę
    if http_status in {401, 403, 429, 503}:
        return True, f"status_{http_status}", "error"

    # 2) sygnatury treści (CloudFront / WAF / CAPTCHA)
    if _contains_any(h, CLOUD_ERROR_SIGNS):
        return True, "cloudfront_403", "error"

    if _contains_any(h, WAF_CAPTCHA_SIGNS):
        return True, "waf_or_captcha", "error"

    # brak znanych oznak – zwróć oryginał
    return False, "", html or ""
