#!/opt/homebrew/bin/python3
# 심층분석 프리필터: 스테일 제거 + X논쟁축 분류 + 신뢰계정 우선 + 일정 스캔
import json, sys
from datetime import datetime, timezone, timedelta
from email.utils import parsedate_to_datetime

BASE = "/Users/sean/Claude/Projects/에이전트구축/"
HOURS = int(sys.argv[1]) if len(sys.argv) > 1 else 30

def pdt(s):
    if not s: return None
    for f in (lambda x: parsedate_to_datetime(x),
              lambda x: datetime.fromisoformat(x.replace("Z","+00:00"))):
        try:
            d = f(s); return d if d.tzinfo else d.replace(tzinfo=timezone.utc)
        except: pass
    return None

cut = datetime.now(timezone.utc) - timedelta(hours=HOURS)
BLOCK = ['fool.com','motley','simplywall','tipranks','marketbeat','quiver','barchart',
 '247wallst','moomoo','stocktwits','beincrypto','kalkine','nai500','trefis','yahoo',
 'seeking alpha','24/7','startup fortune','indexbox','market research','global market',
 'ad-hoc','tomshardware','thestreet']
TRUST = ['jukan','semianalysis','revoai','pequity','hicagr','alisvolat','drnhj','melvin','mirage']
AXES = {
 'AI모델/추론': ['kimi','k3','moonshot','qwen','deepseek','glm','z.ai','minimax','inference','추론','추론비용','kv','제본스','jevons','active param','활성 파라미터','오픈웨이트','open-weight'],
 '메모리': ['memory','메모리','dram','hbm','cxmt','micron','hynix','asp','lta','trendforce','sndk','nand','2028','oversupply','과잉공급','glut','공급완화','공급 완화','완화','부족 완화','신규 라인','증설','capacity','팹','fab','과잉','oversupplied','normaliz'],
 '광학/CPO': ['optical','광','tsem','lite','cpo','photonics','포토닉스','inp','crdo','aaoi','coupe'],
 '캐펙스/전주지갑': ['capex','캐펙스','depreciation','감가','roic','hyperscaler','bond','채권'],
 '네오클라우드': ['nbis','crwv','iren','neocloud','네오클라우드'],
 '지정학/유가': ['iran','hormuz','호르무즈','oil','유가','전쟁','opec'],
 '일정/정책': ['cpi','pce','fomc','fed','금리','earnings','실적','어닝','트럼프','trump','tariff','관세','export','수출규제','ban','금지'],
}

def load(fn, kind):
    seen=set(); rows=[]
    try: f=open(BASE+fn, encoding='utf-8')
    except: return rows
    for line in f:
        try: d=json.loads(line)
        except: continue
        u=d.get('url','')
        if u in seen: continue
        seen.add(u)
        ts = pdt(d.get('pub','')) or pdt(d.get('ts',''))
        if not ts or ts<cut: continue
        src=(d.get('source','')+' '+d.get('author','')+' '+u).lower()
        if kind=='media' and any(b in src for b in BLOCK): continue
        txt=' '.join(d.get('text','').split())
        rows.append((ts, d.get('source','') or d.get('author',''), txt, src))
    return rows

media=load('media_feed.jsonl','media')
x=load('x_feed.jsonl','x')
print(f"=== 심층분석 프리필터 (최근 {HOURS}h, 스테일·블랙리스트 제거) ===")
print(f"미디어 {len(media)}건 / X {len(x)}건")
print()

for axis, kws in AXES.items():
    hits=[r for r in x if any(k in (r[2]+' '+r[3]).lower() for k in kws)]
    if not hits: continue
    hits.sort(key=lambda r: r[0])
    hits.sort(key=lambda r: any(t in r[3] for t in TRUST), reverse=True)
    print(f"----- [{axis}] X {len(hits)}건 (*=신뢰계정) -----")
    for ts,a,t,src in hits[:12]:
        star='*' if any(tr in src for tr in TRUST) else ' '
        print(f"{star}{ts.strftime('%d %H:%M')} @{a[:14]}: {t[:170]}")
    print()

print("======= 미디어 1차소스 헤드라인 (시간순) =======")
PRIMARY=['reuters','bloomberg','wsj','cnbc','financial time','nyt','new york times','ap news','centcom','guardian','pbs','npr']
prim=[r for r in media if any(p in r[3] for p in PRIMARY)]
prim.sort()
for ts,s,t,src in prim[:40]:
    print(f"{ts.strftime('%d %H:%M')} [{s[:14]}] {t[:120]}")

# ── 공포·환희 지수 (피드 감정 스코어링) ──
FEAR = ['crash','plunge','selloff','폭락','급락','추락','붕괴','공포','panic','fear','bubble','거품','bearish','약세',
 'liquidation','청산','마진콜','margin call','downgrade','하향','miss','쇼크','shock','우려','concern','risk-off',
 '리스크오프','warning','경고','loss','손실','dump','투매','capitulat','항복','recession','침체','collapse','war','전쟁']
GREED = ['surge','rally','폭등','급등','ath','신고가','breakout','돌파','bullish','강세','beat','서프라이즈','surprise',
 'upgrade','상향','record','사상최대','moon','euphoria','환희','buy','매수','accumulate','매집','undervalued','저평가',
 'top pick','반등','rebound','strong','견조','boom','호황','opportunity','기회']

def fear_greed(rows):
    fp=gp=0; fn=gn=0
    for ts,a,t,src in rows:
        tl=(t+' '+src).lower()
        f=sum(1 for w in FEAR if w in tl); g=sum(1 for w in GREED if w in tl)
        if f>g: fn+=1; fp+=f
        elif g>f: gn+=1; gp+=g
    tot=fp+gp
    idx=int(gp/tot*100) if tot else 50
    return idx, fn, gn, fp, gp

fi_x=fear_greed(x); fi_m=fear_greed(media)
fi_all=fear_greed(x+media)
print()
print('======= 공포·환희 지수 =======')
lbl=lambda i:'극단적공포' if i<25 else '공포' if i<45 else '중립' if i<55 else '탐욕' if i<75 else '극단적탐욕'
print(f'종합: {fi_all[0]}/100 ({lbl(fi_all[0])})  | 부정피드 {fi_all[1]}건 vs 긍정피드 {fi_all[2]}건')
print(f'  X:   {fi_x[0]}/100 ({lbl(fi_x[0])})  부정{fi_x[1]}/긍정{fi_x[2]}')
print(f'  미디어:{fi_m[0]}/100 ({lbl(fi_m[0])})  부정{fi_m[1]}/긍정{fi_m[2]}')
print('  (0=극단공포, 100=극단탐욕. 어휘빈도 기반 근사)')
