import argparse
import csv
import subprocess
import sys
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo

from dotenv import load_dotenv
import os

load_dotenv(Path(".env"))

sys.path.insert(0, str(Path(__file__).parent))
from src.ibkr_client import IBKRClient
import strategy

ET = ZoneInfo("America/New_York")

def ts():
    return datetime.now(ET).strftime("[%H:%M:%S ET]")

parser = argparse.ArgumentParser()
parser.add_argument("--symbol", required=True)
parser.add_argument("--check-only", action="store_true")
parser.add_argument("--claude-only", action="store_true")
args = parser.parse_args()

# Hard guard: paper flag vs port
paper = os.getenv("PAPER_TRADING", "false").lower() == "true"
port = int(os.getenv("IBKR_PORT", 7497))
if paper and port in (7496, 4001):
    sys.exit("ABORT: paper flag but live port")
if not paper and port in (7497, 4002):
    sys.exit("ABORT: live flag but paper port")

# Daily trade count
trades_path = Path("trades.csv")
if not trades_path.exists():
    with open(trades_path, "w", newline="") as f:
        csv.writer(f).writerow(["timestamp_iso", "symbol", "side", "size", "fill_price", "order_id", "status"])

today_et = datetime.now(ET).date().isoformat()
max_trades = int(os.getenv("MAX_TRADES_PER_DAY", 5))
today_buys = 0
with open(trades_path, newline="") as f:
    for row in csv.DictReader(f):
        if row["side"] == "BUY" and row["timestamp_iso"].startswith(today_et):
            today_buys += 1

if today_buys >= max_trades:
    print(f"{ts()} Max trades per day ({max_trades}) reached. Exiting.")
    sys.exit(0)

# Connect
host = os.getenv("IBKR_HOST", "127.0.0.1")
client_id = int(os.getenv("IBKR_CLIENT_ID", 2))

try:
    ibkr = IBKRClient(host, port, client_id)
except Exception as e:
    print(f"{ts()} IBKR connection failed: {e}")
    sys.exit(1)

try:
    # Evaluate
    result = strategy.evaluate(args.symbol, ibkr.ib)
    print(f"{ts()} Strategy result: {result}")

    if args.check_only:
        print(f"{ts()} --check-only: exiting without trading.")
        sys.exit(0)

    if not result["pass"]:
        print(f"{ts()} Not trading. Reasons: {result['reasons']}")
        sys.exit(0)

    price = result["price"]

    # Claude approval gate (also triggered by --claude-only)
    import claude_filter
    approved, claude_response = claude_filter.approve(args.symbol, price, result["reasons"])
    print(f"{ts()} Claude says: {claude_response}")
    if not approved or args.claude_only:
        if args.claude_only:
            print(f"{ts()} --claude-only: exiting without trading.")
        else:
            print(f"{ts()} Claude rejected the trade. Exiting.")
        sys.exit(0)

    if price <= 0:
        print(f"{ts()} Price unavailable. Exiting.")
        sys.exit(0)

    # Size position
    portfolio = float(os.getenv("PORTFOLIO_VALUE_USD", 25000))
    max_trade = float(os.getenv("MAX_TRADE_SIZE_USD", 2500))
    budget = min(max_trade, portfolio * 0.10)
    quantity = int(budget / price)

    if quantity < 1:
        print(f"{ts()} Position too small at ${price:.2f}. Exiting.")
        sys.exit(0)

    print(f"{ts()} Sizing: budget=${budget:.2f} price=${price:.2f} qty={quantity}")

    # Spawn trade.py
    cmd = [sys.executable, str(Path("trade.py")), "--symbol", args.symbol, "--side", "BUY", "--size", str(quantity)]
    print(f"{ts()} Spawning: {' '.join(cmd)}")

    try:
        proc = subprocess.run(cmd, timeout=30, capture_output=True, text=True)
        print(f"{ts()} trade.py stdout: {proc.stdout.strip()}")
        if proc.returncode != 0:
            print(f"{ts()} trade.py failed: {proc.stderr.strip()}")
            sys.exit(1)
    except subprocess.TimeoutExpired:
        print(f"{ts()} trade.py timed out. Killing.")
        sys.exit(1)

    # Read last row of trades.csv
    last_row = None
    with open(trades_path, newline="") as f:
        for row in csv.DictReader(f):
            last_row = row
    if last_row and last_row["status"] not in ("Cancelled", "ApiCancelled", "Inactive"):
        print(f"{ts()} SUCCESS: {last_row}")
    else:
        print(f"{ts()} FAILURE: {last_row}")

finally:
    ibkr.disconnect()
