"""sync_mt5_history.py - ?MT5?????????trading_brain.db

?????
    python -m src.sync_mt5_history            # ????90?
    python -m src.sync_mt5_history --days 30   # ?????
    python -m src.sync_mt5_history --watch     # ????????60??????
    python -m src.sync_mt5_history --rebuild   # ????

???MetaTrader5????????MT5????????
"""
import sys, json, sqlite3, time, argparse
from datetime import datetime, timedelta, timezone
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
DB_PATH = ROOT / "data" / "learning" / "trading_brain.db"

sys.path.insert(0, str(ROOT))


def _get_mt5_history(days_back=90):
    """?MT5??XAUUSD????"""
    try:
        import MetaTrader5 as mt5
    except ImportError:
        print("[sync_mt5] ERROR: MetaTrader5 not installed")
        return None

    if not mt5.initialize():
        print(f"[sync_mt5] MT5 init failed: {mt5.last_error()}")
        return None

    now = datetime.now()
    start = now - timedelta(days=days_back)
    history = mt5.history_deals_get(start, now)
    mt5.shutdown()

    if history is None:
        print(f"[sync_mt5] No history data (error: {mt5.last_error()})")
        return None

    # Filter: XAUUSD, non-zero profit (close deals)
    return [d for d in history if d.symbol == "XAUUSD" and d.profit != 0]


def sync_to_brain(days_back=90, rebuild=False):
    """??MT5???brain DB"""
    deals = _get_mt5_history(days_back)
    if deals is None:
        return 0, 0, 0.0

    conn = sqlite3.connect(str(DB_PATH))
    cur = conn.cursor()

    if rebuild:
        cur.execute("DELETE FROM trade_events")
        cur.execute("DELETE FROM sqlite_sequence WHERE name='trade_events'")
        cur.execute("DELETE FROM agent_judgments")
        cur.execute("DELETE FROM loss_lessons")
        existing = set()
        print("[sync_mt5] Rebuilding brain DB from scratch")
    else:
        existing = set(
            row[0] for row in conn.execute(
                "SELECT ticket FROM trade_events WHERE ticket > 0"
            ).fetchall()
        )

    now_iso = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
    inserted = 0

    for d in deals:
        if d.ticket in existing:
            continue
        side = "BUY" if d.type == 0 else "SELL"
        ts = datetime.fromtimestamp(d.time).isoformat()
        cur.execute("""
            INSERT INTO trade_events 
            (ticket, side, entry_price, volume_lots, pnl, is_win, closed_at, created_at, strategy_id)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
        """, (d.ticket, side, d.price, d.volume, round(d.profit, 2),
              1 if d.profit > 0 else 0, ts, now_iso))
        inserted += 1
        existing.add(d.ticket)

    conn.commit()
    count = conn.execute("SELECT COUNT(*) FROM trade_events").fetchone()[0]
    pnl = conn.execute("SELECT COALESCE(SUM(pnl), 0) FROM trade_events").fetchone()[0]
    wins = conn.execute("SELECT COUNT(*) FROM trade_events WHERE is_win=1").fetchone()[0]
    conn.close()

    wr = wins / max(count, 1) * 100
    print(f"[sync_mt5] Synced: +{inserted} new, total {count} trades, "
          f"PnL=${pnl:.2f}, WR={wr:.1f}%, Balance from MT5 TBD")
    return inserted, count, pnl


def watch_loop(interval_sec=60, days_back=7):
    """???????interval_sec??????days_back????"""
    print(f"[sync_mt5] Watch mode: syncing every {interval_sec}s (past {days_back} days)")
    while True:
        try:
            sync_to_brain(days_back=days_back)
        except Exception as e:
            print(f"[sync_mt5] Watch error: {e}")
        time.sleep(interval_sec)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Sync MT5 trade history to brain DB")
    parser.add_argument("--days", type=int, default=90, help="Days of history to sync")
    parser.add_argument("--rebuild", action="store_true", help="Clear and rebuild from scratch")
    parser.add_argument("--watch", action="store_true", help="Continuous watch mode")
    parser.add_argument("--interval", type=int, default=60, help="Watch interval in seconds")
    args = parser.parse_args()

    if args.watch:
        watch_loop(interval_sec=args.interval, days_back=args.days)
    else:
        sync_to_brain(days_back=args.days, rebuild=args.rebuild)