import os,json,datetime,re,subprocess
root='/home/agent/.local/state/CryptoTradingBot'
exp=root+'/experiments'
strategies=['candidate_v62_loose_trend_rebound','candidate_v62_scalp_fast_rebound','candidate_v63_loose_fast_decay','candidate_v64_squeeze_survival_strict','candidate_v64_squeeze_survival_wide','candidate_v65_signal_sampler_aggressive','candidate_v65_signal_sampler_conservative','candidate_v66_squeeze_breakout_sampler','v59_1_frequency_boost','v60_survival','v61_tight_survival','candidate_v67_trend_pullback_sma_vwap','candidate_v68_bollinger_rsi_mean_reversion','candidate_v69_squeeze_breakout_confirmed','candidate_v73_multi_day_trend_investment']
now=datetime.datetime.now().astimezone(); today=now.date().isoformat()
print('NOW',now.isoformat())
print('PID_STATUS')
summary=[]
errpat=re.compile(r'ERROR|FATAL|Traceback|Exception|CRITICAL',re.I)
riskpat=re.compile(r'risk|gate|cooldown|guard|blocked|near miss|near_miss',re.I)
for s in strategies:
    d=os.path.join(exp,s); pf=os.path.join(d,'bot.pid')
    pid=None; alive=False; cmd=''; etime=''
    if os.path.exists(pf):
        try: pid=open(pf).read().strip()
        except Exception as e: pid='ERR:'+str(e)
        if pid and pid.isdigit() and os.path.exists('/proc/'+pid):
            alive=True
            try: cmd=open('/proc/%s/cmdline'%pid,'rb').read().replace(b'\x00',b' ').decode(errors='replace').strip()
            except Exception: pass
            try: etime=subprocess.check_output(['ps','-p',pid,'-o','etime='],text=True).strip()
            except Exception: pass
    print(json.dumps({'strategy':s,'pid':pid,'alive':alive,'etime':etime,'cmd':cmd},ensure_ascii=False))
print('STRATEGY_SUMMARY')
for s in strategies:
    d=os.path.join(exp,s); journal=os.path.join(d,'Tradeanalyse','trade_journal.jsonl'); statef=os.path.join(d,'paper_state.json'); logf=os.path.join(d,'bot.log'); tlog=os.path.join(d,'Tradeanalyse','trading_log.txt'); near=os.path.join(d,'Tradeanalyse','near_miss.jsonl')
    entries=exits=0; today_entries=today_exits=0; realized=0.0; today_realized=0.0; last_trade_ts=None
    if os.path.exists(journal):
        with open(journal,errors='replace') as f:
            for line in f:
                line=line.strip()
                if not line: continue
                try: obj=json.loads(line)
                except Exception: continue
                typ=str(obj.get('event') or obj.get('type') or obj.get('action') or '').lower()
                ts=str(obj.get('timestamp') or obj.get('ts') or obj.get('time') or obj.get('datetime') or '')
                if ts: last_trade_ts=ts
                is_entry=('entry' in typ or 'buy' in typ or 'open' in typ) and not ('near' in typ)
                is_exit=('exit' in typ or 'sell' in typ or 'close' in typ)
                if is_entry: entries+=1; today_entries += int(ts.startswith(today))
                if is_exit:
                    exits+=1; today_exits += int(ts.startswith(today))
                    pnl=None
                    for k in ['pnl','realized_pnl','profit','profit_loss','pnl_usd','net_pnl']:
                        if k in obj:
                            try: pnl=float(obj[k]); break
                            except Exception: pass
                    if pnl is not None:
                        realized+=pnl
                        if ts.startswith(today): today_realized+=pnl
    open_positions=0; unreal=0.0; state_keys=[]
    if os.path.exists(statef):
        try:
            st=json.load(open(statef)); state_keys=list(st.keys())[:20]
            def count_pos(x):
                c=0
                if isinstance(x,dict):
                    for key in ['positions','open_positions','paper_positions']:
                        v=x.get(key)
                        if isinstance(v,list): c+=sum(1 for p in v if p and (not isinstance(p,dict) or str(p.get('status','open')).lower()!='closed'))
                        elif isinstance(v,dict): c+=sum(1 for p in v.values() if p and (not isinstance(p,dict) or str(p.get('status','open')).lower()!='closed'))
                    c+=sum(count_pos(v) for v in x.values() if isinstance(v,(dict,list)))
                elif isinstance(x,list): c+=sum(count_pos(v) for v in x)
                return c
            open_positions=count_pos(st)
            def first_num(keys,x):
                if isinstance(x,dict):
                    for k,v in x.items():
                        if k in keys:
                            try: return float(v)
                            except Exception: pass
                    for v in x.values():
                        if isinstance(v,(dict,list)):
                            r=first_num(keys,v)
                            if r is not None: return r
                elif isinstance(x,list):
                    for v in x:
                        r=first_num(keys,v)
                        if r is not None: return r
                return None
            unreal=first_num({'unrealized_pnl','unrealized_pnl_usd','paper_unrealized_pnl'},st) or 0.0
        except Exception as e: state_keys=['STATE_ERR '+str(e)]
    errors=[]; risks=[]
    for lf in [logf,tlog]:
        if os.path.exists(lf):
            try:
                lines=open(lf,errors='replace').read().splitlines()[-300:]
                errors += [ln[-240:] for ln in lines if errpat.search(ln)][-3:]
                risks += [ln[-240:] for ln in lines if riskpat.search(ln)][-3:]
            except Exception as e: errors.append('read_err '+lf+' '+str(e))
    near_count=0; near_recent=[]
    if os.path.exists(near):
        try:
            with open(near,errors='replace') as f:
                for line in f:
                    near_count+=1; near_recent.append(line.strip()[:220]); near_recent=near_recent[-3:]
        except Exception: pass
    rec={'strategy':s,'entries':entries,'exits':exits,'open':open_positions,'realized':round(realized,6),'today_entries':today_entries,'today_exits':today_exits,'today_realized':round(today_realized,6),'unrealized':round(unreal,6),'errors':errors,'risk_events':risks,'near_miss_count':near_count,'near_recent':near_recent,'state_keys':state_keys,'last_trade_ts':last_trade_ts}
    summary.append(rec); print(json.dumps(rec,ensure_ascii=False))
print('TOTALS',json.dumps({'entries':sum(r['entries'] for r in summary),'exits':sum(r['exits'] for r in summary),'open':sum(r['open'] for r in summary),'realized':round(sum(r['realized'] for r in summary),6),'today_entries':sum(r['today_entries'] for r in summary),'today_exits':sum(r['today_exits'] for r in summary),'today_realized':round(sum(r['today_realized'] for r in summary),6)},ensure_ascii=False))
print('MARKET_CONTEXT')
mc=os.path.join(root,'market_context.jsonl')
if os.path.exists(mc):
    lines=open(mc,errors='replace').read().splitlines()
    for line in lines[-5:]:
        try: print(json.dumps(json.loads(line),ensure_ascii=False)[:4000])
        except Exception: print(line[:1000])
print('COLLECTOR_LOG_TAIL')
cl=os.path.join(root,'market_context_collector.log')
if os.path.exists(cl): print('\n'.join(open(cl,errors='replace').read().splitlines()[-20:]))
