"""Представление индикатора URL и шаблоны его поиска."""

from __future__ import annotations

import re
import logging
from dataclasses import dataclass, field
from typing import Any, FrozenSet, Mapping
from urllib.parse import urlparse

from .analysis import IndicatorAnalysisMixin, build_kaspersky_zone_verdict
from .patterns import PatternDefinition
from .reason_texts import (
    KASPERSKY_URL_BLOCK_REASON,
    KASPERSKY_URL_MONITOR_REASON,
    KASPERSKY_URL_OK_REASON,
)

_URL_PATTERN = re.compile(
    r"[a-z][a-z0-9+\-.]*(?::|\[:\])//[^\s\"'<>]+", re.IGNORECASE
)
_DOT_OBFUSCATION = re.compile(r"\[\.]|\[\]|\(dot\)|\[dot\]|\(\.\)", re.IGNORECASE)
_HTTP_OBFUSCATION = re.compile(r"^(hxxp|h___p|httx|hpp)", re.IGNORECASE)
_COLON_OBFUSCATION = re.compile(r"\[:\]")

_logger = logging.getLogger(__name__)


@dataclass(frozen=True)
class URLIndicator(IndicatorAnalysisMixin):
    """Индикатор, описывающий URL."""

    value: str
    kinds: FrozenSet[str] = field(default_factory=frozenset)

    @property
    def category(self) -> str:
        """Категория индикатора."""

        return "url"

    @property
    def hostname(self) -> str:
        """Хостовая часть URL."""

        parsed = urlparse(self.value)
        if parsed.hostname:
            return parsed.hostname
        return self.value

    def pre_analysis(self) -> dict[str, Any]:
        """Отсутствие быстрых правил перед сетевыми запросами."""

        _logger.info(
            "Для URL %s нет быстрых правил, переходим к опросу провайдеров", self.value
        )
        return {}

    def analysis(self, features: Mapping[str, Any] | None = None) -> dict[str, Any]:
        """Анализ URL по зоне Kaspersky."""

        prepared_features = features or {}
        _logger.info("Проверяем зону Kaspersky для URL %s", self.value)

        verdict = build_kaspersky_zone_verdict(
            prepared_features,
            block_reason=KASPERSKY_URL_BLOCK_REASON,
            monitor_reason=KASPERSKY_URL_MONITOR_REASON,
            ok_reason=KASPERSKY_URL_OK_REASON,
        )

        return {
            "features": prepared_features,
            "status": "ok",
            **verdict,
        }


def _restore_http(value: str) -> str:
    return _HTTP_OBFUSCATION.sub("http", value)


def _rearm_dots(value: str) -> str:
    return _DOT_OBFUSCATION.sub(".", value)


def _prepare_url(value: str) -> str:
    restored_scheme = _restore_http(value)
    restored_colon = _COLON_OBFUSCATION.sub(":", restored_scheme)
    cleaned = _rearm_dots(restored_colon)
    return cleaned.rstrip(",.;")


def build_patterns() -> tuple[PatternDefinition, ...]:
    """Вернуть правило выделения URL."""

    return (
        PatternDefinition(
            name="url",
            regex=_URL_PATTERN,
            factory=lambda value, kinds: URLIndicator(value=value, kinds=kinds),
            kinds=frozenset({"url"}),
            rearm=_prepare_url,
            normalize=lambda value: value,
        ),
    )
