"""Провайдер репутации MalwareBazaar для хешей."""

from __future__ import annotations

from contextlib import AbstractAsyncContextManager, asynccontextmanager
import logging
from typing import Any, AsyncIterator

import httpx

from ..iocs import IOCType
from .base import BaseProvider, FeatureValue
from .utils import ensure_mapping, normalize_text

TOKEN_NAME = "malwarebazaar"

logger = logging.getLogger(__name__)


class MalwareBazaarProvider(BaseProvider):
    """Получает сведения о хешах через API MalwareBazaar."""

    API_URL = "https://mb-api.abuse.ch/api/v1/"

    def __init__(self) -> None:
        super().__init__("malwarebazaar", requires_token=True, token_name=TOKEN_NAME)

    def get_context(
        self, token: str | None = None
    ) -> AbstractAsyncContextManager[httpx.AsyncClient]:
        """Создать HTTP-клиент с авторизационным заголовком."""

        if not token:
            raise ValueError("Для MalwareBazaar требуется API-токен")

        headers = {"Auth-Key": token, "Accept": "application/json"}
        logger.debug(
            "Создаём HTTP-клиент MalwareBazaar: прокси=%s, таймаут=%.2f",
            self.http_proxy or "не используется",
            self.http_timeout,
        )

        @asynccontextmanager
        async def _client() -> AsyncIterator[httpx.AsyncClient]:
            client_kwargs = self.build_http_client_kwargs(
                base_url=self.API_URL,
                headers=headers,
            )
            async with httpx.AsyncClient(**client_kwargs) as client:
                yield client

        return _client()

    async def fetch(self, indicator: IOCType, context: Any) -> dict[str, Any] | bool:
        """Запросить сведения о хеше в MalwareBazaar."""

        if indicator.category != "hash":
            logger.info(
                "MalwareBazaar обрабатывает только хеши, пропускаем индикатор %s (%s)",
                indicator.value,
                indicator.category,
            )
            return False

        logger.info("Запрашиваем MalwareBazaar для хеша %s", indicator.value)

        try:
            response = await context.post("", data={"query": "get_info", "hash": indicator.value})
            response.raise_for_status()
            return response.json()
        except Exception as exc:  # noqa: BLE001
            logger.exception(
                "Не удалось получить данные MalwareBazaar для %s: %s",
                indicator.value,
                exc,
            )
            return False

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

        payload_map = ensure_mapping(payload, source="MalwareBazaar")
        query_status = normalize_text(payload_map.get("query_status"))
        sample_records = payload_map.get("data") or []
        has_response = bool(sample_records)
        sample_sha256 = None

        if query_status and query_status != "ok":
            logger.info(
                "MalwareBazaar вернул статус %s для хеша %s",
                query_status,
                getattr(indicator, "value", indicator),
            )

        if sample_records:
            sample_payload = ensure_mapping(sample_records[0], source="MalwareBazaar data")
            sample_sha256 = normalize_text(sample_payload.get("sha256_hash"))

        return {
            "malbazaar_has_response": has_response,
            "malbazaar_sha256": sample_sha256,
        }
