#!/usr/bin/env python3
"""
TheCryptoClaw Daily Market Briefing
Fetches fundamentals from free APIs and generates a formatted report.
Sources: CoinGecko, Alternative.me, CoinGlass (where available)
"""

import json
import urllib.request
import urllib.error
import datetime
import sys

TIMEOUT = 15

def fetch_json(url):
    """Fetch JSON from URL with error handling."""
    try:
        req = urllib.request.Request(url, headers={
            'User-Agent': 'TheCryptoClaw/1.0',
            'Accept': 'application/json'
        })
        with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
            return json.loads(resp.read().decode())
    except Exception as e:
        return {"_error": str(e)}

def get_fear_greed():
    """Fear & Greed Index from Alternative.me"""
    data = fetch_json("https://api.alternative.me/fng/?limit=7")
    if "_error" in data:
        return None
    entries = data.get("data", [])
    if not entries:
        return None
    current = entries[0]
    history = entries[1:] if len(entries) > 1 else []
    return {
        "value": int(current["value"]),
        "classification": current["value_classification"],
        "history": [{"value": int(e["value"]), "class": e["value_classification"]} for e in history]
    }

def get_btc_price():
    """BTC price, volume, market cap from CoinGecko"""
    data = fetch_json(
        "https://api.coingecko.com/api/v3/simple/price"
        "?ids=bitcoin&vs_currencies=usd"
        "&include_24hr_change=true&include_24hr_vol=true&include_market_cap=true"
    )
    if "_error" in data or "bitcoin" not in data:
        return None
    btc = data["bitcoin"]
    return {
        "price": btc.get("usd", 0),
        "change_24h": btc.get("usd_24h_change", 0),
        "volume_24h": btc.get("usd_24h_vol", 0),
        "market_cap": btc.get("usd_market_cap", 0)
    }

def get_global_data():
    """Global crypto market data from CoinGecko"""
    data = fetch_json("https://api.coingecko.com/api/v3/global")
    if "_error" in data or "data" not in data:
        return None
    g = data["data"]
    return {
        "total_market_cap_usd": g.get("total_market_cap", {}).get("usd", 0),
        "total_volume_usd": g.get("total_volume", {}).get("usd", 0),
        "btc_dominance": g.get("market_cap_percentage", {}).get("btc", 0),
        "eth_dominance": g.get("market_cap_percentage", {}).get("eth", 0),
        "market_cap_change_24h": g.get("market_cap_change_percentage_24h_usd", 0),
        "active_cryptos": g.get("active_cryptocurrencies", 0),
    }

def get_btc_7d_chart():
    """7-day price history from CoinGecko"""
    data = fetch_json(
        "https://api.coingecko.com/api/v3/coins/bitcoin/market_chart"
        "?vs_currency=usd&days=7&interval=daily"
    )
    if "_error" in data or "prices" not in data:
        return None
    prices = data["prices"]
    result = []
    for ts, price in prices:
        dt = datetime.datetime.utcfromtimestamp(ts / 1000)
        result.append({"date": dt.strftime("%b %d"), "price": price})
    return result

def get_top_coins():
    """Top 10 coins from CoinGecko"""
    data = fetch_json(
        "https://api.coingecko.com/api/v3/coins/markets"
        "?vs_currency=usd&order=market_cap_desc&per_page=10&page=1"
        "&sparkline=false&price_change_percentage=24h,7d"
    )
    if "_error" in data or not isinstance(data, list):
        return None
    coins = []
    for c in data:
        coins.append({
            "symbol": c.get("symbol", "").upper(),
            "name": c.get("name", ""),
            "price": c.get("current_price", 0),
            "change_24h": c.get("price_change_percentage_24h", 0) or 0,
            "change_7d": c.get("price_change_percentage_7d_in_currency", 0) or 0,
            "market_cap": c.get("market_cap", 0),
            "volume": c.get("total_volume", 0),
        })
    return coins

def get_trending():
    """Trending coins from CoinGecko"""
    data = fetch_json("https://api.coingecko.com/api/v3/search/trending")
    if "_error" in data or "coins" not in data:
        return None
    trending = []
    for item in data["coins"][:7]:
        coin = item.get("item", {})
        trending.append({
            "name": coin.get("name", ""),
            "symbol": coin.get("symbol", ""),
            "market_cap_rank": coin.get("market_cap_rank", "N/A"),
        })
    return trending

def fmt_usd(val, decimals=0):
    """Format large USD values"""
    if val >= 1_000_000_000_000:
        return f"${val/1_000_000_000_000:.2f}T"
    elif val >= 1_000_000_000:
        return f"${val/1_000_000_000:.2f}B"
    elif val >= 1_000_000:
        return f"${val/1_000_000:.2f}M"
    elif decimals > 0:
        return f"${val:,.{decimals}f}"
    else:
        return f"${val:,.0f}"

def fear_emoji(val):
    if val <= 20:
        return "🔴"
    elif val <= 40:
        return "🟠"
    elif val <= 60:
        return "🟡"
    elif val <= 80:
        return "🟢"
    else:
        return "💚"

def change_emoji(val):
    if val > 3:
        return "🟢🟢"
    elif val > 0:
        return "🟢"
    elif val > -3:
        return "🔴"
    else:
        return "🔴🔴"

def generate_briefing():
    """Generate the full daily briefing."""
    now = datetime.datetime.utcnow()
    
    # Fetch all data
    btc = get_btc_price()
    fng = get_fear_greed()
    glob = get_global_data()
    chart = get_btc_7d_chart()
    top = get_top_coins()
    trending = get_trending()
    
    lines = []
    lines.append(f"🦾 CRYPTOCLAW DAILY BRIEFING")
    lines.append(f"📅 {now.strftime('%B %d, %Y')} — {now.strftime('%H:%M')} UTC")
    lines.append("")
    
    # === BTC PRICE ===
    if btc:
        chg = btc['change_24h']
        lines.append(f"━━━ BTC PRICE ━━━")
        lines.append(f"💰 ${btc['price']:,.0f} {change_emoji(chg)} ({chg:+.1f}%)")
        lines.append(f"📊 24h Vol: {fmt_usd(btc['volume_24h'])}")
        lines.append(f"🏦 Mkt Cap: {fmt_usd(btc['market_cap'])}")
        lines.append("")
    
    # === 7-DAY CHART ===
    if chart and len(chart) > 1:
        lines.append(f"━━━ 7-DAY TREND ━━━")
        high = max(p["price"] for p in chart)
        low = min(p["price"] for p in chart)
        for p in chart:
            # Simple text bar chart
            pct = (p["price"] - low) / (high - low) if high != low else 0.5
            bar = "█" * int(pct * 12) + "░" * (12 - int(pct * 12))
            lines.append(f"{p['date']}: {bar} ${p['price']:,.0f}")
        chg_7d = ((chart[-1]["price"] / chart[0]["price"]) - 1) * 100
        lines.append(f"7d Change: {chg_7d:+.1f}%")
        lines.append("")
    
    # === FEAR & GREED ===
    if fng:
        lines.append(f"━━━ FEAR & GREED ━━━")
        lines.append(f"{fear_emoji(fng['value'])} {fng['value']}/100 — {fng['classification']}")
        if fng['history']:
            hist_vals = [str(h['value']) for h in fng['history'][:6]]
            lines.append(f"Past 6 days: {' → '.join(hist_vals)}")
        
        # Algo insight based on F&G
        if fng['value'] <= 25:
            lines.append(f"⚡ ALGO NOTE: Extreme fear = high vol. Grid will be active, sub-pairs grinding hard.")
        elif fng['value'] >= 75:
            lines.append(f"⚡ ALGO NOTE: Extreme greed = potential reversal. Grid ready to catch it.")
        else:
            lines.append(f"⚡ ALGO NOTE: Neutral sentiment = sideways likely. Sub-pair repeat paradise.")
        lines.append("")
    
    # === GLOBAL MARKET ===
    if glob:
        lines.append(f"━━━ GLOBAL CRYPTO MARKET ━━━")
        lines.append(f"📈 Total Cap: {fmt_usd(glob['total_market_cap_usd'])} ({glob['market_cap_change_24h']:+.1f}%)")
        lines.append(f"🔵 BTC Dom: {glob['btc_dominance']:.1f}%")
        lines.append(f"🟣 ETH Dom: {glob['eth_dominance']:.1f}%")
        lines.append(f"📊 24h Vol: {fmt_usd(glob['total_volume_usd'])}")
        lines.append("")
    
    # === TOP 10 ===
    if top:
        lines.append(f"━━━ TOP 10 MOVERS ━━━")
        for c in top:
            lines.append(f"{c['symbol']:>5}: ${c['price']:>10,.2f} {change_emoji(c['change_24h'])} {c['change_24h']:+5.1f}% (7d: {c['change_7d']:+.1f}%)")
        lines.append("")
    
    # === TRENDING ===
    if trending:
        lines.append(f"━━━ TRENDING 🔥 ━━━")
        for t in trending:
            rank = f"#{t['market_cap_rank']}" if t['market_cap_rank'] != "N/A" else ""
            lines.append(f"• {t['name']} ({t['symbol']}) {rank}")
        lines.append("")
    
    # === ALGO ALIGNMENT ===
    lines.append(f"━━━ ALGO ALIGNMENT ━━━")
    if btc:
        vol_ratio = btc['volume_24h'] / btc['market_cap'] * 100 if btc['market_cap'] > 0 else 0
        if abs(btc['change_24h']) > 5:
            lines.append(f"🔥 HIGH VOL DAY: {abs(btc['change_24h']):.1f}% move")
            lines.append(f"   → Grid levels likely triggered, recovery pairs active")
            lines.append(f"   → Adaptive grid scaling UP (wider spacing)")
        elif abs(btc['change_24h']) < 1:
            lines.append(f"😴 LOW VOL DAY: Only {abs(btc['change_24h']):.1f}% move")
            lines.append(f"   → Sub-pair repeats printing in sideways chop")
            lines.append(f"   → Adaptive grid scaling DOWN (tighter spacing)")
        else:
            lines.append(f"📊 NORMAL VOL: {abs(btc['change_24h']):.1f}% move")
            lines.append(f"   → Standard grid operation, balanced entries")
        
        lines.append(f"   → Vol/MCap ratio: {vol_ratio:.2f}%")
    lines.append("")
    
    # === ECONOMIC CALENDAR REMINDERS ===
    # Hardcoded key dates (update monthly)
    lines.append(f"━━━ KEY DATES AHEAD ━━━")
    # These would ideally come from an API, but we maintain manually
    upcoming = get_upcoming_events(now)
    for evt in upcoming:
        lines.append(f"📌 {evt}")
    if not upcoming:
        lines.append("   (No major events in next 7 days)")
    lines.append("")
    
    lines.append(f"— TheCryptoClaw 🦾")
    
    return "\n".join(lines)

def get_upcoming_events(now):
    """
    Key economic/crypto events. 
    Updated manually or via API when available.
    Format: (month, day, description)
    """
    events_2026 = [
        # FOMC 2026 (estimated based on typical schedule)
        (1, 29, "FOMC Rate Decision"),
        (2, 12, "CPI Data Release"),
        (2, 14, "Retail Sales Data"),
        (3, 7, "Jobs Report (NFP)"),
        (3, 12, "CPI Data Release"),
        (3, 18, "FOMC Rate Decision"),
        (4, 10, "CPI Data Release"),
        (4, 29, "FOMC Rate Decision"),
        (5, 8, "Jobs Report (NFP)"),
        (5, 13, "CPI Data Release"),
        (6, 10, "CPI Data Release"),
        (6, 17, "FOMC Rate Decision"),
        (7, 10, "CPI Data Release"),
        (7, 29, "FOMC Rate Decision"),
        (8, 12, "CPI Data Release"),
        (9, 10, "CPI Data Release"),
        (9, 16, "FOMC Rate Decision"),
        (10, 14, "CPI Data Release"),
        (10, 28, "FOMC Rate Decision"),
        (11, 12, "CPI Data Release"),
        (12, 9, "CPI Data Release"),
        (12, 16, "FOMC Rate Decision"),
        # Crypto-specific
        (3, 15, "ETH Pectra Upgrade (tentative)"),
        (4, 15, "US Tax Deadline — potential sell pressure"),
    ]
    
    upcoming = []
    for month, day, desc in events_2026:
        try:
            evt_date = datetime.datetime(now.year, month, day)
            delta = (evt_date - now).days
            if 0 <= delta <= 14:
                upcoming.append(f"{evt_date.strftime('%b %d')} ({delta}d) — {desc}")
        except ValueError:
            pass
    
    return upcoming[:5]  # Max 5 events


if __name__ == "__main__":
    report = generate_briefing()
    print(report)
    
    # Optionally save to file
    if "--save" in sys.argv:
        now = datetime.datetime.utcnow()
        fname = f"results/briefing_{now.strftime('%Y%m%d_%H%M')}.txt"
        with open(fname, "w") as f:
            f.write(report)
        print(f"\nSaved to {fname}")
