"""MetaSleuth (BlockSec AML) source — live API at aml.blocksec.com.

Endpoint: POST https://aml.blocksec.com/address-label/api/v3/labels
  Headers: API-KEY: <key>
  Body: {"chain_id": 1, "address": "0x..."}

Verified working: 2026-06-22 (Binance 0x3d12... returned main_entity=Binance,
entity categories EXCHANGE + OTC DESK).

Limit: 10 calls/day per API key on the free tier. So we cache aggressively.
"""
from __future__ import annotations

import asyncio
import logging
import os
from datetime import UTC, datetime

import httpx

from app.domain.labels.models import Label, LabelSource

log = logging.getLogger(__name__)

METASLEUTH_BASE = "https://aml.blocksec.com/address-label/api/v3"
# Free tier: 10 calls/day per key on risk-level, similar on labels
DEFAULT_TIMEOUT = 8.0

# Chain name -> MetaSleuth chain_id
_CHAIN_MAP = {
    "ethereum": 1,
    "bitcoin": -1,
    "tron": -2,
    "solana": -3,
    "monero": -4,
    "sui": 5,
    "optimism": 10,
    "cronos": 25,
    "bsc": 56,
    "base": 8453,
    "arbitrum": 42161,
    "polygon": 137,
}


async def query_metasleuth(address: str, chain: str = "ethereum") -> list[Label]:
    """Query MetaSleuth for an address's entity info.

    Returns:
        - 1 entity label with the main entity name (e.g. "Binance")
        - Optional category labels (EXCHANGE, OTC DESK, etc.)
        - Attributes (DEPOSIT ADDRESS, etc.)
    """
    api_key = os.getenv("METASLEUTH_LABELS_API_KEY", "")
    if not api_key:
        # Try gopass via the standard pattern
        try:
            import subprocess

            result = subprocess.run(
                ["gopass", "show", "-o", "rmi/infra/metasleuth_labels_api_key"],
                capture_output=True, text=True, timeout=2,
            )
            if result.returncode == 0 and result.stdout.strip():
                api_key = result.stdout.strip()
        except Exception:
            pass

    if not api_key:
        log.debug("metasleuth_no_api_key configured, skipping")
        return []

    chain_id = _CHAIN_MAP.get(chain.lower())
    if chain_id is None:
        log.debug("metasleuth_unsupported_chain chain=%s", chain)
        return []

    def _call_api() -> dict:
        """Sync HTTP call (run in thread)."""
        try:
            r = httpx.post(
                f"{METASLEUTH_BASE}/labels",
                headers={"API-KEY": api_key, "Content-Type": "application/json"},
                json={"chain_id": chain_id, "address": address},
                timeout=DEFAULT_TIMEOUT,
            )
            r.raise_for_status()
            data = r.json()
            if data.get("code") == 200000:
                return data.get("data") or {}
            log.warning("metasleuth_api_err code=%s msg=%s", data.get("code"), data.get("message"))
            return {}
        except httpx.HTTPError as e:
            log.warning("metasleuth_api_http_err: %s", e)
            return {}
        except Exception as e:
            log.warning("metasleuth_api_err: %s", e)
            return {}

    data = await asyncio.to_thread(_call_api)
    if not data:
        return []

    labels: list[Label] = []
    main_entity = data.get("main_entity")
    if main_entity:
        labels.append(Label(
            address=address.lower(),
            chain=chain,
            label_type="entity",
            label_value=main_entity,
            source=LabelSource.METASLEUTH,
            confidence=0.95,
            verified_at=datetime.now(UTC),
            entity=main_entity,
            entity_category=_first_category(data),
            attributes=_extract_attributes(data),
        ))

    # Also emit labels for each category
    categories = data.get("main_entity_info", {}).get("categories", [])
    if not isinstance(categories, list):
        categories = []
    for cat in categories:
        if not isinstance(cat, dict):
            continue
        cat_name = cat.get("name")
        if cat_name and cat_name != main_entity:
            labels.append(Label(
                address=address.lower(),
                chain=chain,
                label_type="category",
                label_value=cat_name,
                source=LabelSource.METASLEUTH,
                confidence=0.9,
                verified_at=datetime.now(UTC),
                entity=main_entity,
                entity_category=cat_name,
                attributes={"code": cat.get("code")},
            ))

    return labels


def _first_category(data: dict) -> str | None:
    """Extract first category name from MetaSleuth response."""
    cats = data.get("main_entity_info", {}).get("categories", [])
    if cats and isinstance(cats[0], dict):
        return cats[0].get("name")
    return None


def _extract_attributes(data: dict) -> dict:
    """Extract attributes from MetaSleuth response."""
    attrs = data.get("main_entity_info", {}).get("attributes", [])
    out = {}
    for a in attrs:
        if isinstance(a, dict):
            name = a.get("name", "")
            if name:
                out[name] = a.get("code")
    # Add description (website/twitter) if present
    desc = data.get("main_entity_info", {}).get("description", {})
    if isinstance(desc, dict):
        for k, v in desc.items():
            if v:
                out[k] = v
    return out
