#!/usr/bin/env python3
import json, os, sys, time, datetime as dt, urllib.request, urllib.error

ROOT = os.path.expanduser("~/kleiner")
DATA = os.path.join(ROOT, "data")
ENVF = os.path.join(ROOT, ".env.json")
WATCHLIST = os.path.join(DATA, "watchlist.json")
OUT = os.path.join(DATA, "quotes.json")
INTRA = os.path.join(DATA, "intraday")

def load_env():
    with open(ENVF,"r",encoding="utf-8") as f: return json.load(f)

def http_get(url, timeout=25):
    req = urllib.request.Request(url, headers={"Accept":"application/json"})
    with urllib.request.urlopen(req, timeout=timeout) as r:
        return json.loads(r.read().decode("utf-8"))

def read_watchlist():
    w = json.load(open(WATCHLIST,"r",encoding="utf-8"))
    if isinstance(w, list) and w and isinstance(w[0], dict):
        return [x.get("symbol","").upper() for x in w if x.get("symbol")]
    return [str(x).upper() for x in w]

def latest_from_intraday(tk, label):
    p = os.path.join(INTRA, f"{tk}_{label}.json")
    if not os.path.exists(p): return None
    arr = json.load(open(p,"r",encoding="utf-8"))
    if not arr: return None
    last = arr[-1]
    return (float(last.get("c",0.0)), last.get("ts",""))

def prev_close(tk, key):
    js = http_get(f"https://api.polygon.io/v2/aggs/ticker/{tk}/prev?adjusted=true&apiKey={key}")
    r = (js.get("results") or [{}])[0]
    return float(r.get("c", 0.0))

def last_price_today_minute(tk, key):
    # Minute-Aggregates von HEUTE; nimm die letzte Kerze als "aktuellen" Kurs
    today = dt.date.today().isoformat()
    url = f"https://api.polygon.io/v2/aggs/ticker/{tk}/range/1/minute/{today}/{today}?adjusted=true&sort=asc&limit=50000&apiKey={key}"
    js = http_get(url)
    res = js.get("results") or []
    if not res: return None, None
    last = res[-1]
    ts = dt.datetime.utcfromtimestamp(int(last["t"])/1000).replace(microsecond=0).isoformat()+"Z"
    return float(last["c"]), ts

def build_quote(tk, key):
    pc = 0.0
    try: pc = prev_close(tk, key)
    except Exception: pass

    # 1) Primär: Minute-Aggregates (heute)
    try:
        px, ts = last_price_today_minute(tk, key)
        if px:
            chg = px - pc if pc else 0.0
            chg_pct = (chg/pc*100.0) if pc else 0.0
            return {"symbol":tk,"price":round(px,2),"prevClose":round(pc,2),
                    "change":round(chg,2),"changePct":round(chg_pct,2),"last":ts}
    except Exception:
        pass

    # 2) Fallback: aus Intraday 15m
    px_ts = latest_from_intraday(tk, "15m")
    if not px_ts:
        px_ts = latest_from_intraday(tk, "1h")
    if px_ts:
        px, ts = px_ts
        chg = px - pc if pc else 0.0
        chg_pct = (chg/pc*100.0) if pc else 0.0
        return {"symbol":tk,"price":round(px,2),"prevClose":round(pc,2),
                "change":round(chg,2),"changePct":round(chg_pct,2),"last":ts}

    # 3) Letzter Ausweg: nur Prev Close
    if pc:
        return {"symbol":tk,"price":round(pc,2),"prevClose":round(pc,2),
                "change":0.0,"changePct":0.0,"last":"prevClose"}

    return None

def main():
    try:
        key = load_env()["POLYGON_KEY"]
        tickers = read_watchlist()
        out = []
        for tk in tickers:
            q = build_quote(tk, key)
            if q: out.append(q)
            time.sleep(0.15)
        tmp = OUT + ".tmp"
        with open(tmp,"w",encoding="utf-8") as f:
            json.dump(out, f, ensure_ascii=False, separators=(",",":"))
        os.replace(tmp, OUT)
        print("quotes ok:", len(out))
    except Exception as e:
        print("error:", e); sys.exit(1)

if __name__=="__main__":
    main()
