"""Malware C2 / URLhaus feed (abuse.ch, Osiris port)."""
from __future__ import annotations

import logging
from datetime import datetime, timezone
from typing import Any

from services.fetchers._store import _data_lock, _mark_fresh, is_any_active, latest_data
from services.network_utils import fetch_with_curl

logger = logging.getLogger(__name__)

COUNTRY_CENTROIDS: dict[str, tuple[float, float]] = {
    "AF": (65, 33), "AL": (20, 41), "DZ": (3, 28), "AR": (-64, -34), "AU": (134, -25),
    "AT": (14, 47.5), "BE": (4, 50.8), "BR": (-51, -10), "CA": (-96, 62), "CN": (105, 35),
    "DE": (10, 51), "FR": (2, 46), "GB": (-2, 54), "IN": (79, 22), "IR": (53, 32),
    "IT": (12.5, 42.8), "JP": (138, 36), "KR": (128, 36), "MX": (-102, 23.5), "NL": (5.5, 52.5),
    "PL": (19.5, 52), "RU": (100, 60), "SG": (103.8, 1.35), "TW": (121, 23.7), "UA": (32, 49),
    "US": (-97, 38), "VN": (106, 16),
}


def fetch_malware_threats() -> list[dict[str, Any]]:
    if not is_any_active("malware_c2"):
        return latest_data.get("malware_threats") or []

    threats: list[dict[str, Any]] = []
    threat_id = 0

    try:
        resp = fetch_with_curl(
            "https://feodotracker.abuse.ch/downloads/ipblocklist.json",
            timeout=10,
            headers={"User-Agent": "Shadowbroker/1.0", "Accept": "application/json"},
        )
        if resp.status_code == 200:
            entries = resp.json()
            if not isinstance(entries, list):
                entries = []
            for entry in entries[:200]:
                cc = entry.get("country")
                if not cc or cc not in COUNTRY_CENTROIDS:
                    continue
                lng, lat = COUNTRY_CENTROIDS[cc]
                j_lng = ((threat_id * 173.7) % 200 - 100) / 100 * 4
                j_lat = ((threat_id * 293.1) % 200 - 100) / 100 * 4
                threats.append(
                    {
                        "id": f"feodo-{threat_id}",
                        "lat": lat + j_lat,
                        "lng": lng + j_lng,
                        "ip": entry.get("ip_address") or "unknown",
                        "port": entry.get("dst_port") or 0,
                        "malware": entry.get("malware") or "unknown",
                        "status": entry.get("status") or "active",
                        "first_seen": entry.get("first_seen"),
                        "last_online": entry.get("last_online"),
                        "country": cc,
                        "threat_type": "botnet_c2",
                    }
                )
                threat_id += 1
    except Exception as exc:
        logger.warning("Feodo fetch failed: %s", exc)

    try:
        resp = fetch_with_curl(
            "https://urlhaus-api.abuse.ch/v1/urls/recent/limit/100/",
            timeout=8,
        )
        if resp.status_code == 200:
            urls = (resp.json() or {}).get("urls") or []
            for u in urls:
                cc = u.get("country")
                if not cc or cc not in COUNTRY_CENTROIDS:
                    cc = next(iter(COUNTRY_CENTROIDS))
                lng, lat = COUNTRY_CENTROIDS[cc]
                j_lng = ((threat_id * 137.3) % 200 - 100) / 100 * 5
                j_lat = ((threat_id * 211.7) % 200 - 100) / 100 * 5
                threats.append(
                    {
                        "id": f"urlhaus-{threat_id}",
                        "lat": lat + j_lat,
                        "lng": lng + j_lng,
                        "ip": u.get("host") or "unknown",
                        "port": 0,
                        "malware": ", ".join(u.get("tags") or []) or u.get("threat") or "malware",
                        "status": u.get("url_status") or "online",
                        "first_seen": u.get("dateadded"),
                        "country": cc,
                        "threat_type": "malware_url",
                    }
                )
                threat_id += 1
    except Exception as exc:
        logger.debug("URLhaus supplement failed: %s", exc)

    payload = {
        "threats": threats,
        "total": len(threats),
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "source": "abuse.ch Feodo Tracker + URLhaus",
    }
    with _data_lock:
        latest_data["malware_threats"] = payload
    _mark_fresh("malware_threats")
    return threats
