# -*- coding: utf-8 -*-
"""
Data Source Registry — 数据来源注册表
每个数据项都标注其确切来源，便于审计和排错。
"""

# ═══════════════════════════════════════════════════════════
# 数据源定义
# ═══════════════════════════════════════════════════════════

SOURCES = {
    # Market Data
    "okx_rest": {
        "name": "OKX REST API",
        "url": "https://www.okx.com/api/v5/",
        "type": "exchange",
        "refresh": "per-cycle (60s)",
        "provides": ["candles", "ticker", "orderbook", "oi", "funding_rate",
                     "taker_volume", "liquidations", "positions", "balance"],
    },
    "okx_ws": {
        "name": "OKX WebSocket",
        "url": "wss://ws.okx.com:8443/ws/v5/public",
        "type": "exchange",
        "refresh": "real-time (books5)",
        "provides": ["orderbook_snapshot", "spoofing_detect", "toxic_flow_input"],
    },
    "deribit_rest": {
        "name": "Deribit REST API",
        "url": "https://www.deribit.com/api/v2/",
        "type": "exchange",
        "refresh": "per-cycle (60s)",
        "provides": ["options_greeks", "iv", "max_pain", "open_interest"],
    },

    # News & Sentiment
    "blockbeats": {
        "name": "BlockBeats API",
        "url": "https://api.theblockbeats.news/v1/open-api/open-flash",
        "type": "news",
        "refresh": "15s polling",
        "provides": ["flash_news_cn", "news_input"],
    },
    "treeofalpha": {
        "name": "TreeOfAlpha API",
        "url": "https://news.treeofalpha.com/api/news",
        "type": "news",
        "refresh": "60s polling",
        "provides": ["flash_news_en", "news_input"],
    },
    "telegram_channels": {
        "name": "Telegram Channels (Telethon)",
        "channels": "ediporcoin, FinanceNewsDaily, bimi_chs, wublock, jinseBTC",
        "type": "news",
        "refresh": "real-time (MTProto)",
        "provides": ["channel_news", "news_input"],
    },
    "deepseek_ai": {
        "name": "DeepSeek API",
        "url": "https://api.deepseek.com/v1/chat/completions",
        "type": "ai_analysis",
        "refresh": "per-request (~5s)",
        "provides": ["news_scoring", "sentiment_analysis", "key_news_extraction"],
    },
    "fear_greed": {
        "name": "Alternative.me Fear & Greed Index",
        "url": "https://api.alternative.me/fng/",
        "type": "sentiment",
        "refresh": "per-cycle (60s)",
        "provides": ["fng_value", "fng_classification"],
    },

    # On-chain & Macro
    "etherscan": {
        "name": "Etherscan API",
        "url": "https://api.etherscan.io/api",
        "type": "onchain",
        "refresh": "per-cycle (120s)",
        "provides": ["smart_money_tx", "copy_trading_signals"],
    },
    "yahoo_finance": {
        "name": "Yahoo Finance (yfinance)",
        "type": "macro",
        "refresh": "per-request (cached 5min)",
        "provides": ["macro_prices", "correlation_matrix", "btc_corr"],
    },
    "coingecko": {
        "name": "CoinGecko API",
        "url": "https://api.coingecko.com/api/v3/",
        "type": "macro",
        "refresh": "per-request (cached 30min)",
        "provides": ["global_volume", "liquidity_data"],
    },

    # Database
    "mysql": {
        "name": "MySQL (coinglass_trader)",
        "host": "127.0.0.1:3306",
        "type": "storage",
        "refresh": "continuous",
        "provides": ["factor_snapshots", "trades", "equity_history",
                     "news_memory", "position_snapshots", "system_events"],
    },

    # Computed / Derived
    "computed": {
        "name": "Local Computation",
        "type": "derived",
        "provides": [
            "indicators (EMA/ATR/RSI/ADX/Bollinger)",
            "signals (15-factor composite)",
            "toxic_flow_score",
            "anomaly_events",
            "strategy_signals",
            "mm_retreat_score",
            "price_prediction",
        ],
    },
}

# ═══════════════════════════════════════════════════════════
# 快捷函数
# ═══════════════════════════════════════════════════════════

def source(name: str) -> dict:
    """获取数据源信息"""
    return SOURCES.get(name, {"name": name, "type": "unknown"})


def tag(value, src: str, **meta):
    """给数据附加来源标签"""
    return {"_source": src, "_source_info": source(src), "value": value, **meta}


def tag_dict(data: dict, src: str) -> dict:
    """给字典附加来源"""
    return {"_source": src, "_source_name": source(src)["name"], **data}


def get_all_sources() -> list:
    """列出所有数据源"""
    return [{"key": k, "name": v["name"], "type": v["type"],
             "provides": v.get("provides", [])} for k, v in SOURCES.items()]


def source_report() -> str:
    """数据源报告（文本）"""
    lines = ["=== 数据源报告 ==="]
    for key, info in SOURCES.items():
        name = info["name"]
        stype = info["type"]
        provides = ", ".join(info.get("provides", [])[:4])
        refresh = info.get("refresh", info.get("channels", "N/A"))
        lines.append(f"  [{stype}] {name}")
        lines.append(f"         → {provides}  ({refresh})")
    return "\n".join(lines)
