#!/usr/bin/env python3
# IntelligentCoordinator v1.0 - Codex Generated
import json,time,pathlib,threading,os,datetime
from collections import defaultdict

class Paths:
    def __init__(self):
        self.appdata = pathlib.Path(os.environ.get("APPDATA","")) / "GoldAutoTrade"
        self.engine_dir = pathlib.Path(__file__).resolve().parent
    @property
    def ledger(self): return self.appdata / 'logs/trading_ledger.ndjson'
    @property
    def blackboard(self): return self.appdata / 'blackboard_state.json'
    @property
    def help_dir(self):
        p = self.appdata / 'logs/help_requests'
        p.mkdir(parents=True,exist_ok=True); return p
P = Paths()

def read_ledger(n=100):
    if not P.ledger.exists(): return []
    t=[]
    try:
        with open(P.ledger,"r",encoding="utf-8") as f:
            for line in f:
                line=line.strip()
                if line:
                    try: t.append(json.loads(line))
                    except: pass
    except: pass
    return t[-n:]

def log(msg):
    lp=P.appdata / "logs" / "coordinator_log.ndjson"
    lp.parent.mkdir(parents=True,exist_ok=True)
    e={"ts":datetime.datetime.now().isoformat(),"role":"Coordinator","type":"INFO","text":msg}
    try:
        with open(lp,"a",encoding="utf-8") as f:
            f.write(json.dumps(e,ensure_ascii=False)+"\n")
    except: pass
    fmt = chr(37)+chr(72)+chr(58)+chr(37)+chr(77)+chr(58)+chr(37)+chr(83)
    print(f"[{datetime.datetime.now().strftime(fmt)}] {msg}")

def analyze():
    trades=read_ledger(50)
    if len(trades)<10: return None
    perf=defaultdict(lambda:{'w':0,'l':0,'p':0.0})
    for t in trades:
        sid=t.get("strategy_id") or t.get("selected_strategy_id") or "unknown"
        pnl=float(t.get("pnl",0) or 0)
        perf[sid]["p"]+=pnl
        if pnl>0: perf[sid]["w"]+=1
        elif pnl<0: perf[sid]["l"]+=1
    issues=[]
    for sid,s in perf.items():
        total=s["w"]+s["l"]
        if total>=5:
            wr=s["w"]/total
            if wr<0.35 and s["p"]<-30:
                issues.append(f"{sid}:WR={wr:.0%} PnL=${s[chr(112)]:.0f}")
    con_loss=0
    for t in reversed(trades):
        if float(t.get("pnl",0) or 0)<0: con_loss+=1
        else: break
    if con_loss>=5 and issues:
        req={"ts":datetime.datetime.now().isoformat(),"title":f"连续{con_loss}笔亏损","context":{"issues":issues,"consecutive":con_loss},"status":"pending"}
        hf=P.help_dir / f"help_{int(time.time())}.json"
        hf.write_text(json.dumps(req,indent=2,ensure_ascii=False),encoding="utf-8")
        log(f"求助: 连续{con_loss}笔亏损 + {len(issues)}个策略异常")
    return {
        "perf":{k:{"wr":round((v["w"]/(v["w"]+v["l"]+0.01))*100,1),"pnl":round(v["p"],2)} for k,v in perf.items() if v["w"]+v["l"]>=3},
        "consecutive_losses":con_loss
    }

if __name__=="__main__":
    print("IntelligentCoordinator v1.0 | Codex Generated")
    print(f"Watch: {P.appdata}")

    def loop():
        tick=0
        while True:
            try:
                tick+=1
                result=analyze()
                if result and result.get('perf'):
                    if tick%6==0:
                        log(f"策略健康: {json.dumps(result['perf'])}")
                if tick%180==0 and result:
                    log(f"深度检查: ledger={len(read_ledger(5000))}条 连亏={result.get('consecutive_losses',0)}")
                time.sleep(10)
            except Exception as e:
                log(f"loop error: {e}")
                time.sleep(30)

    threading.Thread(target=loop,daemon=True).start()
    log("Coordinator started")
    try:
        while True: time.sleep(60)
    except KeyboardInterrupt:
        print("Stopped")
