#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json, os, re, sys, datetime
import yfinance as yf

BASE = os.path.expanduser("~/Claude/Projects/에이전트구축")
MEDIA = os.path.join(BASE, "media_feed.jsonl")
XFEED = os.path.join(BASE, "x_feed.jsonl")
REJECT = os.path.join(BASE, "rejected_feed.jsonl")
GAPLOG = os.path.join(BASE, "gap_log.jsonl")
NQLEV = os.path.join(BASE, "nq_levels.py")
DRY = "--dry" in sys.argv
THRESH = 5.0

WATCH = {
    "MU": ["마이크론", "Micron"], "SNDK": ["샌디스크", "SanDisk"],
    "NBIS": ["네비우스", "Nebius"], "AAOI": ["Applied Optoelectronics"],
    "SOXL": [], "NVDA": ["엔비디아", "Nvidia"],
    "META": ["메타", "Meta Platforms"], "LITE": ["루멘텀", "Lumentum"],
    "TER": ["테라다인", "Teradyne"], "ALAB": ["아스테라", "Astera Labs"],
    "COHR": ["코히런트", "Coherent"], "MRVL": ["마벨", "Marvell"],
    "CRDO": ["크레도", "Credo"], "GLW": ["코닝", "Corning"],
    "AVGO": ["브로드컴", "Broadcom"], "CIEN": ["시에나", "Ciena"],
    "AEHR": ["Aehr"], "ASML": [], "LRCX": ["램리서치", "Lam Research"],
    "AMAT": ["Applied Materials"], "KLAC": ["KLA"],
    "AMD": ["Advanced Micro"], "INTC": ["인텔", "Intel"],
    "TSM": ["TSMC", "Taiwan Semiconductor"], "IBM": [],
    "NOW": ["서비스나우", "ServiceNow"], "CRM": ["세일즈포스", "Salesforce"],
    "ACN": ["액센츄어", "Accenture"], "JPM": ["JPMorgan", "JP Morgan"],
    "MSFT": ["Microsoft"], "GOOGL": ["구글", "Google", "Alphabet"],
    "AMZN": ["아마존", "Amazon"], "ORCL": ["오라클", "Oracle"],
    "CRWV": ["코어위브", "CoreWeave"], "IREN": ["Iris Energy"],
}

def creds():
    try:
        s = open(NQLEV, encoding="utf-8").read()
        return (re.search(r'BOT_TOKEN\s*=\s*["\']([^"\']+)', s).group(1),
                re.search(r'CHAT_ID\s*=\s*["\']?([^"\'\s]+)', s).group(1))
    except Exception:
        return None, None

def send(msg):
    import urllib.request, urllib.parse
    tok, cid = creds()
    if not tok:
        print("[!] 토큰 없음"); return
    d = urllib.parse.urlencode({"chat_id": cid, "text": msg,
                                "disable_web_page_preview": "true"}).encode()
    urllib.request.urlopen(f"https://api.telegram.org/bot{tok}/sendMessage", d, timeout=15)

def feed_text(days=2):
    now = datetime.datetime.now(datetime.timezone.utc)
    buf = []
    for p in (MEDIA, XFEED, REJECT):
        if not os.path.exists(p): continue
        for line in open(p, "rb"):
            try: d = json.loads(line.decode("utf-8", "replace"))
            except Exception: continue
            ts = d.get("ts") or d.get("pub") or ""
            try: t = datetime.datetime.fromisoformat(str(ts).replace("Z", "+00:00"))
            except Exception: continue
            if t.tzinfo is None: t = t.replace(tzinfo=datetime.timezone.utc)
            if (now - t).days <= days:
                buf.append((d.get("text", ""), p.endswith("rejected_feed.jsonl")))
    return buf

def main():
    px = yf.download(list(WATCH), period="5d", interval="1d",
                     progress=False, auto_adjust=False)["Close"]
    moves = {}
    for tk in WATCH:
        try:
            s = px[tk].dropna()
            if len(s) < 2: continue
            ch = (s.iloc[-1] / s.iloc[-2] - 1) * 100
            if abs(ch) >= THRESH: moves[tk] = round(float(ch), 2)
        except Exception:
            continue

    buf = feed_text()
    lines, gaps = [], []
    for tk, ch in sorted(moves.items(), key=lambda x: -abs(x[1])):
        pat = re.compile(r"(?<![A-Za-z])\$?" + tk + r"(?![A-Za-z])")
        al = [a.lower() for a in WATCH[tk]]
        inflow = [r for txt, r in buf
                  if pat.search(txt) or any(a in txt.lower() for a in al)]
        n_all = len(inflow)
        n_rej = sum(1 for r in inflow if r)
        if n_all == 0:
            st = "미포착"; gaps.append({"tk": tk, "chg": ch, "reason": "수집안됨"})
        elif n_all == n_rej:
            st = f"수집됐으나 전량 컷({n_rej}건)"
            gaps.append({"tk": tk, "chg": ch, "reason": "필터오판"})
        else:
            st = f"포착 {n_all - n_rej}건"
        lines.append(f"{tk} {ch:+.2f}% · {st}")

    hdr = f"[그물점검 {datetime.date.today()}] 5% 이상 {len(moves)}종목"
    msg = hdr + "\n" + ("\n".join(lines) if lines else "해당 없음")
    if gaps:
        msg += "\n\n구멍 " + str(len(gaps)) + "건 — 룰 수정 논의 필요"
        with open(GAPLOG, "a", encoding="utf-8") as f:
            for g in gaps:
                g["date"] = str(datetime.date.today())
                f.write(json.dumps(g, ensure_ascii=False) + "\n")
    print(msg)
    if not DRY: send(msg)

if __name__ == "__main__":
    main()
