import os
import json
import time
from datetime import datetime, timezone, timedelta
from pathlib import os
import sys
from pathlib import Path

# 确保可以导入项目根目录下的 config_manager
ROOT = Path(__file__).parent.parent.absolute()
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))
import config_manager

# 动态获取路径
MT5_FILES = config_manager.get_mt5_dir()
if not MT5_FILES:
    MT5_FILES = ROOT / "test_mt5_files"
    
BRIDGE_DIR = MT5_FILES / "gold_autotrade" / "bridge"
LEDGER_FILE = config_manager.get_logs_dir() / "trading_ledger.ndjson"

def sync_history():
    req_file = BRIDGE_DIR / "to_ea" / "history_sync.request.json"
    req_file.parent.mkdir(parents=True, exist_ok=True)
    
    # 写入请求，让 EA 导出历史
    req = {
        "signal_id": "history_sync",
        "action": "EXPORT_HISTORY",
        "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
        "days": 30
    }
    req_file.write_text(json.dumps(req))
    print("已发送历史记录导出请求给 EA, 正在等待响应...")
    
    # 等待 EA 处理并生成 history.json
    resp_file = BRIDGE_DIR / "from_ea" / "history_sync.history.json"
    timeout = 10
    start_time = time.time()
    
    while time.time() - start_time < timeout:
        if resp_file.exists():
            print("收到 EA 响应，开始处理数据...")
            try:
                data = json.loads(resp_file.read_text())
                process_history_data(data)
            except Exception as e:
                print(f"解析历史数据失败: {e}")
            finally:
                resp_file.unlink(missing_ok=True)
            return
        time.sleep(0.5)
        
    print("超时：未能获取到 EA 的历史记录响应。请检查 EA 是否正常运行并已重新编译。")

def process_history_data(data):
    deals = data.get("deals", [])
    print(f"共获取到 {len(deals)} 条原始成交记录。")
    if not deals:
        return
        
    # 按 position_id 分组
    positions = {}
    for d in deals:
        pid = str(d.get("position_id"))
        if pid not in positions:
            positions[pid] = []
        positions[pid].append(d)
        
    print(f"原始记录涉及 {len(positions)} 个 Position ID。")
    
    # 构造 ledger 格式
    new_records = []
    for pid, pdeals in positions.items():
        # pdeals 按照时间排序
        pdeals.sort(key=lambda x: x.get("time", 0))
        
        # 寻找 entry (entry_type=0, 对应 DEAL_ENTRY_IN) 
        # MT5 DEAL_ENTRY: 0=IN, 1=OUT, 2=INOUT, 3=OUT_BY
        # 兼容性检查：有些平台可能记录为字符串，有些为数字
        entries = [x for x in pdeals if str(x.get("entry_type")) == "0"]
        closes = [x for x in pdeals if str(x.get("entry_type")) in ["1", "3"]]
        
        if not entries:
            # 如果没有明显的 IN，尝试把第一笔成交当做入场（容错处理）
            entry_deal = pdeals[0]
        else:
            entry_deal = entries[0]
            
        # deal_type: 0 = BUY, 1 = SELL
        side = "BUY" if str(entry_deal.get("type")) == "0" else ("SELL" if str(entry_deal.get("type")) == "1" else "UNKNOWN")
        
        entry_time = datetime.fromtimestamp(entry_deal.get("time"), tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
        
        if closes:
            close_deal = closes[-1] # 取最后一个平仓动作
            close_time = datetime.fromtimestamp(close_deal.get("time"), tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
            # 累加所有的 profit
            total_profit = sum(float(x.get("profit", 0)) for x in pdeals) # 整个持仓生命周期的盈亏和
            
            record = {
                "ts": entry_time,
                "action": "CLOSE",
                "side": side,
                "volume": float(entry_deal.get("volume", 0)),
                "entry": float(entry_deal.get("price", 0)),
                "exit": float(close_deal.get("price", 0)),
                "pnl": round(total_profit, 2),
                "ticket": int(pid),
                "status": "FILLED",
                "_recovered_from_ea": True
            }
            new_records.append(record)
            
    if not new_records:
        print("没有提取到符合开平仓逻辑的完整记录。")
        # 打印前5个记录的 entry_type 示例，方便调试
        if deals:
            print("调试信息 - 前5条成交记录详情:")
            for i, d in enumerate(deals[:5]):
                print(f"  {i}: pos_id={d.get('position_id')}, entry_type={d.get('entry_type')}, type={d.get('type')}, profit={d.get('profit')}")
        return
        
    print(f"重构出 {len(new_records)} 笔完整订单记录。")

    # 读取现有 ledger，构建 (ticket → record) 映射
    existing_by_ticket = {}
    if LEDGER_FILE.exists():
        with open(LEDGER_FILE, "r") as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue
                try:
                    rec = json.loads(line)
                    ticket = rec.get("ticket")
                    if ticket:
                        existing_by_ticket[ticket] = rec
                except Exception:
                    pass

    # 增量写入：只写入 MT5 有但 ledger 没有的，或 ledger 中 pnl=0/ticket=0 的损坏记录
    added_count = 0
    updated_count = 0
    all_records = []

    for r in new_records:
        ticket = r["ticket"]
        existing = existing_by_ticket.get(ticket)

        if existing is None:
            # 全新记录，直接追加
            all_records.append(r)
            added_count += 1
        elif float(existing.get("pnl", 0) or 0) == 0 or existing.get("ticket") == 0:
            # 旧记录已损坏（pnl=0 或 ticket=0），用 MT5 数据替换
            all_records.append(r)
            updated_count += 1
        else:
            # 已有有效记录，保留原数据
            all_records.append(existing)

    # 重写整个 ledger（保证顺序：老记录在前，新记录在后）
    with open(LEDGER_FILE, "w") as f:
        for rec in all_records:
            f.write(json.dumps(rec, ensure_ascii=False) + "\n")

    print(f"同步完成：新增 {added_count} 笔，更新 {updated_count} 笔损坏记录（共 {len(all_records)} 笔）")

if __name__ == "__main__":
    sync_history()
