"""Локальный провайдер рейтингов автономных систем ASRank."""

from __future__ import annotations

import csv
import logging
from pathlib import Path
from typing import Any

from .base import BaseProvider, FeatureValue

logger = logging.getLogger(__name__)


class ASRankProvider(BaseProvider):
    """Провайдер, возвращающий ранг ASN на основе локального списка."""

    DATA_PATH = Path(__file__).resolve().parents[2] / "lists" / "asns.csv"

    def __init__(self) -> None:
        """Загрузить данные рейтинга ASRank из CSV."""

        super().__init__("asrank", requires_token=False)
        self._asn_ranks = self._load_ranks()

    def _load_ranks(self) -> dict[int, int]:
        """Подготовить словарь «ASN → ранг» из файла ``asns.csv``."""

        ranks: dict[int, int] = {}

        if not self.DATA_PATH.exists():
            logger.warning("Файл рейтингов ASRank не найден: %s", self.DATA_PATH)
            return ranks

        try:
            with self.DATA_PATH.open(encoding="utf-8") as csv_file:
                reader = csv.DictReader(csv_file)
                for row in reader:
                    asn_raw = str(row.get("asn", "")).strip()
                    rank_raw = str(row.get("rank", "")).strip()
                    if not asn_raw or not rank_raw:
                        logger.debug(
                            "Пропускаем некорректную строку ASRank: asn=%s, rank=%s",
                            asn_raw,
                            rank_raw,
                        )
                        continue
                    try:
                        asn = int(asn_raw)
                        rank = int(rank_raw)
                    except Exception:  # noqa: BLE001
                        logger.debug(
                            "Не удалось преобразовать значения ASRank: asn=%s, rank=%s",
                            asn_raw,
                            rank_raw,
                        )
                        continue
                    ranks[asn] = rank
        except Exception as exc:  # noqa: BLE001
            logger.exception(
                "Ошибка загрузки рейтингов ASRank из %s: %s", self.DATA_PATH, exc
            )
            return {}

        logger.info(
            "Загружено %d рейтингов ASRank из %s", len(ranks), self.DATA_PATH
        )
        return ranks

    def get_rank(self, asn: int | str | None) -> int | None:
        """Вернуть ранг автономной системы или ``None`` при отсутствии."""

        if asn is None:
            logger.info("Не указан ASN для запроса ASRank")
            return None

        try:
            asn_value = int(str(asn).strip())
        except Exception:  # noqa: BLE001
            logger.warning("ASN имеет некорректный формат: %s", asn)
            return None

        rank = self._asn_ranks.get(asn_value)
        if rank is None:
            logger.info("ASN %s отсутствует в рейтинге ASRank", asn_value)
        else:
            logger.debug("ASN %s имеет ранг %d", asn_value, rank)
        return rank

    async def fetch(self, indicator: Any, context: Any) -> dict[str, Any] | bool:
        """Получить ранг ASN. Метод совместим с базовым интерфейсом."""

        rank = self.get_rank(getattr(indicator, "value", indicator))
        if rank is None:
            return False
        return {"asn": int(str(getattr(indicator, "value", indicator)).strip()), "rank": rank}

    def build_features(
        self, payload: Any, *, indicator: Any | None = None
    ) -> dict[str, FeatureValue]:
        """Построить фичи на основе полученного ранга."""

        rank = payload.get("rank") if isinstance(payload, dict) else None
        asn = payload.get("asn") if isinstance(payload, dict) else None
        features = {
            "asrank_asn": asn,
            "asrank_rank": rank,
        }
        logger.debug(
            "Построены фичи ASRank для ASN %s: %s", asn or indicator, features
        )
        return features
