﻿import aiohttp
import math

MEMPOOL_API_BASE = "https://mempool.space/api"


async def fetch_mempool(session: aiohttp.ClientSession):
    """
    מחזיר dict מאוחד עם:
    - tx_count
    - mempool_vsize
    - fee_high
    - block_tx_count

    במידה ויש כשל → מחזיר fallback עם ערכים 0 כדי לא להפיל את הבוט.
    """
    # --------------------------
    # 1) GET MEMPOOL STATUS
    # --------------------------
    try:
        async with session.get(f"{MEMPOOL_API_BASE}/mempool", timeout=6) as res:
            res.raise_for_status()
            mempool = await res.json()
    except Exception as e:
        print(f"[MEMPOOL ERROR] /mempool → {e}")
        return {
            "tx_count": 0.0,
            "mempool_vsize": 0.0,
            "fee_high": 0.0,
            "block_tx_count": 0.0,
        }

    # --------------------------
    # 2) GET RECOMMENDED FEES
    # --------------------------
    try:
        async with session.get(f"{MEMPOOL_API_BASE}/v1/fees/recommended", timeout=6) as res:
            res.raise_for_status()
            fees = await res.json()
    except Exception as e:
        print(f"[MEMPOOL ERROR] /v1/fees/recommended → {e}")
        fees = {"fastestFee": 0}

    # --------------------------
    # 3) GET LATEST BLOCK
    # --------------------------
    try:
        async with session.get(f"{MEMPOOL_API_BASE}/blocks", timeout=6) as res:
            res.raise_for_status()
            blocks = await res.json()
    except Exception as e:
        print(f"[MEMPOOL ERROR] /blocks → {e}")
        blocks = []

    if isinstance(blocks, list) and len(blocks) > 0:
        latest_block = blocks[0]
        block_tx = float(latest_block.get("tx_count", 0.0))
    else:
        block_tx = 0.0

    # --------------------------
    # BUILD CLEAN STRUCT
    # --------------------------
    return {
        "tx_count": float(mempool.get("count", 0.0)),
        "mempool_vsize": float(mempool.get("vsize", 0.0)),
        "fee_high": float(fees.get("fastestFee", 0.0)),
        "block_tx_count": block_tx,
    }


def normalize_mempool(m: dict | None):
    """
    Normalizes mempool data into 3 onchain factors:
    - f_mempool (0–1 range)
    - f_fee (0–1 range)
    - f_block_tx (0–1 range)

    מחזיר שלישיות שמתאימות ל-V6 ENGINE.

    אם m=None → מחזיר (0, 0, 0)
    """
    if not m:
        return 0.0, 0.0, 0.0

    tx_count = m.get("tx_count", 0.0)
    mempool_vsize = m.get("mempool_vsize", 0.0)
    fee_high = m.get("fee_high", 0.0)
    block_tx = m.get("block_tx_count", 0.0)

    # ----------------------------------
    # NORMALIZATION RULES:
    # tanh(x / scale) → יציב, בלי קליפים
    # ----------------------------------

    # עומס בממפול (אפשר לעלות scale לפי הדאטה)
    f_mempool = math.tanh(mempool_vsize / 50_000_000) if mempool_vsize > 0 else 0.0

    # fee_high: בדרך כלל 1–50. מקסימלי לפעמים 200+ בזמן עומס קיצוני
    f_fee = math.tanh(fee_high / 200) if fee_high > 0 else 0.0

    # מספר עסקאות בבלוק: 1500–3500
    f_block_tx = math.tanh(block_tx / 3000) if block_tx > 0 else 0.0

    return f_mempool, f_fee, f_block_tx
