"""
MT5 Client - Bridge File Mode (works on macOS via Wine)
Writes command files and reads responses via MT5TradeServer EA.
No AppleScript, no GUI automation needed.
"""

import json
import os
import time
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, Optional

# MT5 Wine prefix - auto-detect
MT5_PREFIX = None
MT5_FILES = None
for _prefix in [
    Path.home() / "Library/Application Support/net.metaquotes.wine.metatrader5",
    Path.home() / "Library/Application Support/net.metaquotes.wine.metatrader5-beta",
]:
    _files = _prefix / "drive_c/Program Files/MetaTrader 5/MQL5/Files"
    if _files.exists():
        MT5_PREFIX = _prefix
        MT5_FILES = _files
        break

if MT5_FILES is None:
    raise RuntimeError(
        "MT5 Wine MQL5/Files not found. "
        "Is MT5 installed and the Wine prefix accessible?"
    )

CMD_FILE = MT5_FILES / "mt5_cmd.json"
RSP_FILE = MT5_FILES / "mt5_rsp.json"
FILLED_MAGIC = MT5_FILES / "FILLED_MAGIC.txt"  # marker file written by EA


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _log(msg: str) -> None:
    print(f"[{_now()[11:19]}] {msg}")


def _send_and_wait(
    cmd: Dict[str, Any],
    timeout: float = 15.0,
    poll_s: float = 0.2,
) -> Optional[Dict]:
    """
    Write command file, wait for response file.
    Returns response dict or None on timeout.
    """
    # Clear old response
    if RSP_FILE.exists():
        try:
            RSP_FILE.unlink()
        except Exception:
            pass

    # Write command
    with CMD_FILE.open("w", encoding="utf-8") as f:
        json.dump(cmd, f, ensure_ascii=False)

    start = time.time()
    while time.time() - start < timeout:
        if RSP_FILE.exists():
            try:
                resp = json.loads(RSP_FILE.read_text(encoding="utf-8"))
                return resp
            except Exception:
                pass
        time.sleep(poll_s)

    return None


class MT5Client:
    """MT5 trading client using bridge file protocol."""

    def __init__(self, timeout: float = 15.0):
        self.timeout = timeout

    def ping(self) -> Dict:
        r = _send_and_wait({"action": "ping", "ts": _now()}, timeout=5)
        if r:
            return {"success": True, "message": r.get("message", "pong")}
        return {"success": False, "message": "MT5 EA not responding"}

    def get_positions(self) -> Dict:
        r = _send_and_wait({"action": "positions"}, timeout=self.timeout)
        return r or {"success": False, "positions": []}

    def get_account(self) -> Dict:
        r = _send_and_wait({"action": "account"}, timeout=self.timeout)
        return r or {"success": False}

    def get_quote(self, symbol: str = "XAUUSD") -> Dict:
        r = _send_and_wait({"action": "quote", "symbol": symbol}, timeout=self.timeout)
        return r or {"success": False}

    def show_status(self) -> tuple:
        acct = self.get_account()
        positions = self.get_positions()
        quote = self.get_quote()
        return acct, positions, quote

    def buy(
        self,
        symbol: str = "XAUUSD",
        volume: float = 0.01,
        sl: float = 0,
        tp: float = 0,
    ) -> Dict:
        cmd = {
            "action": "buy",
            "symbol": symbol,
            "volume": volume,
            "sl": sl,
            "tp": tp,
            "ts": _now(),
        }
        r = _send_and_wait(cmd, timeout=self.timeout)
        if not r:
            return {"success": False, "message": "MT5 EA timeout"}
        return {"success": r.get("success", False), **r}

    def sell(
        self,
        symbol: str = "XAUUSD",
        volume: float = 0.01,
        sl: float = 0,
        tp: float = 0,
    ) -> Dict:
        cmd = {
            "action": "sell",
            "symbol": symbol,
            "volume": volume,
            "sl": sl,
            "tp": tp,
            "ts": _now(),
        }
        r = _send_and_wait(cmd, timeout=self.timeout)
        if not r:
            return {"success": False, "message": "MT5 EA timeout"}
        return {"success": r.get("success", False), **r}

    def close(self, ticket: int = 0) -> Dict:
        cmd = {"action": "close", "ticket": ticket, "ts": _now()}
        r = _send_and_wait(cmd, timeout=self.timeout)
        if not r:
            return {"success": False, "message": "MT5 EA timeout"}
        return {"success": r.get("success", False), **r}

    def close_all(self) -> Dict:
        return self.close(ticket=0)


# ─── CLI ───────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    import sys

    client = MT5Client()
    cmd = sys.argv[1].lower() if len(sys.argv) > 1 else ""

    if not cmd or cmd == "ping":
        r = client.ping()
        _log(f"{'✅' if r['success'] else '❌'} {r.get('message','')}")
    elif cmd == "status":
        acct, positions, quote = client.show_status()
        print("\n" + "=" * 40)
        print(f"  MT5 Status ({_now()[11:19]})")
        print("=" * 40)
        if acct.get("success"):
            print(f"  Balance: ${acct.get('balance', 0):.2f}")
            print(f"  Equity:  ${acct.get('equity', 0):.2f}")
            print(f"  Profit:  ${acct.get('profit', 0):.2f}")
        if quote.get("success"):
            print(f"  XAUUSD:  {quote.get('bid', 'N/A')} / {quote.get('ask', 'N/A')}")
        if positions.get("success"):
            for p in positions.get("positions", []):
                print(f"  #{p['ticket']} {p['symbol']} {p['type']} "
                      f"v={p['volume']} PnL=${p.get('pnl', 0):.2f}")
        else:
            print("  Positions: none")
        print("=" * 40 + "\n")
    elif cmd == "buy":
        vol = float(sys.argv[2]) if len(sys.argv) > 2 else 0.01
        r = client.buy("XAUUSD", vol)
        _log(f"📈 BUY {'✅' if r['success'] else '❌'} {r.get('message','')}")
    elif cmd == "sell":
        vol = float(sys.argv[2]) if len(sys.argv) > 2 else 0.01
        r = client.sell("XAUUSD", vol)
        _log(f"📉 SELL {'✅' if r['success'] else '❌'} {r.get('message','')}")
    elif cmd == "close":
        r = client.close_all()
        _log(f"🔚 CLOSE {'✅' if r['success'] else '❌'} {r.get('message','')}")
    elif cmd == "quote":
        r = client.get_quote("XAUUSD")
        print(json.dumps(r, indent=2, ensure_ascii=False))
    else:
        print(f"Usage: python3 mt5_client.py [ping|status|buy|sell|close|quote]")
