#!/usr/bin/env python3
"""Refresh weekend/risk-on flow from free public Hyperliquid and Binance APIs."""

from __future__ import annotations

import datetime as dt
import json
import urllib.request
from pathlib import Path


ROOT = Path(__file__).resolve().parent
FLOW_PATH = ROOT / "weekend_flow_state.json"

HELD_TICKERS = ["RDW", "NASA", "MU", "MRVL", "AAOI", "AMD", "GNTA"]
BINANCE_PROXY_SYMBOLS = ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "LINKUSDT", "FETUSDT", "RENDERUSDT"]


def request_json(url: str, payload: dict | None = None) -> dict | list:
    data = None
    headers = {"User-Agent": "codex-personal-market-dashboard/1.0"}
    if payload is not None:
        data = json.dumps(payload).encode("utf-8")
        headers["Content-Type"] = "application/json"
    request = urllib.request.Request(url, data=data, headers=headers)
    with urllib.request.urlopen(request, timeout=18) as response:
        return json.loads(response.read().decode("utf-8"))


def fetch_hyperliquid_universe() -> list[str]:
    data = request_json("https://api.hyperliquid.xyz/info", {"type": "meta"})
    return [item.get("name", "").upper() for item in data.get("universe", []) if item.get("name")]


def fetch_binance_proxy() -> list[dict]:
    rows = []
    for symbol in BINANCE_PROXY_SYMBOLS:
        item = request_json(f"https://api.binance.com/api/v3/ticker/24hr?symbol={symbol}")
        rows.append(
            {
                "symbol": item["symbol"],
                "price": float(item["lastPrice"]),
                "change_pct": round(float(item["priceChangePercent"]), 2),
                "quote_volume_usd": round(float(item["quoteVolume"])),
            }
        )
    return rows


def risk_on_score(proxies: list[dict]) -> int:
    if not proxies:
        return 0
    weighted = 0.0
    total_weight = 0.0
    for item in proxies:
        weight = max(item["quote_volume_usd"], 1)
        weighted += item["change_pct"] * weight
        total_weight += weight
    avg = weighted / total_weight if total_weight else 0.0
    if avg >= 3.0:
        return 3
    if avg >= 1.0:
        return 2
    if avg >= 0.2:
        return 1
    if avg <= -3.0:
        return -3
    if avg <= -1.0:
        return -2
    if avg <= -0.2:
        return -1
    return 0


def build_summary(score: int, proxies: list[dict], direct_coverage: list[str]) -> str:
    leader = max(proxies, key=lambda x: x["quote_volume_usd"], default=None)
    if score > 0:
        tone = "주말 위험선호가 우호적"
    elif score < 0:
        tone = "주말 위험회피가 우세"
    else:
        tone = "주말 플로우는 중립"
    direct = "보유종목 직접 선물 있음" if direct_coverage else "보유주식 직접 선물 없음"
    if not leader:
        return f"{tone}. {direct}. 무료 API 응답이 제한되어 프록시 신뢰도는 낮음."
    return f"{tone}. {direct}. 거래대금 기준 핵심 프록시 {leader['symbol']} {leader['change_pct']:+.2f}%."


def main() -> int:
    errors: list[str] = []
    hyperliquid_universe: list[str] = []
    proxies: list[dict] = []

    try:
        hyperliquid_universe = fetch_hyperliquid_universe()
    except Exception as error:
        errors.append(f"Hyperliquid: {error}")

    try:
        proxies = fetch_binance_proxy()
    except Exception as error:
        errors.append(f"Binance: {error}")

    direct_coverage = sorted(set(HELD_TICKERS) & set(hyperliquid_universe))
    score = risk_on_score(proxies)
    state = {
        "updated_at": dt.datetime.now(dt.timezone.utc).astimezone().isoformat(timespec="seconds"),
        "status": "정상" if not errors else "부분 갱신",
        "risk_on_score": score,
        "summary": build_summary(score, proxies, direct_coverage),
        "direct_coverage": direct_coverage,
        "held_tickers_checked": HELD_TICKERS,
        "hyperliquid_markets_count": len(hyperliquid_universe),
        "proxies": proxies,
        "errors": errors,
        "source_note": "Hyperliquid/Binance 무료 공개 API만 사용. 유료 데이터 없음.",
    }
    FLOW_PATH.write_text(json.dumps(state, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    print(FLOW_PATH)
    print(state["summary"])
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
