"""
monitor.py — watch open positions, trigger stop if price drops below LOD - 1%.
Uses IBKR market data only. Checks every 30s, exits cleanly at 15:51 ET.
"""
import csv
import os
import sys
import time
from datetime import datetime, time as dtime
from pathlib import Path
from zoneinfo import ZoneInfo

from dotenv import load_dotenv

load_dotenv(Path(".env"))
sys.path.insert(0, str(Path(__file__).parent))

from src.ibkr_client import IBKRClient

ET              = ZoneInfo("America/New_York")
FORCE_CLOSE_ET  = dtime(15, 51)
CHECK_INTERVAL  = 30  # seconds

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

host      = os.getenv("IBKR_HOST", "127.0.0.1")
port      = int(os.getenv("IBKR_PORT", 7497))
client_id = int(os.getenv("IBKR_EXEC_CLIENT_ID", 3))

print(f"{ts()} Monitor started. Checking every {CHECK_INTERVAL}s. Stop: LOD - 1%.")

while True:
    now_et = datetime.now(ET).time()
    if now_et >= FORCE_CLOSE_ET:
        print(f"{ts()} 15:51 ET — monitor exiting.")
        sys.exit(0)

    try:
        ibkr = IBKRClient(host, port, client_id)
        positions = ibkr.ib.positions()
    except Exception as e:
        print(f"{ts()} Connection error: {e}")
        time.sleep(CHECK_INTERVAL)
        continue

    for pos in positions:
        symbol = pos.contract.symbol
        qty    = int(pos.position)
        if qty <= 0:
            continue

        try:
            # Live price from market data
            ticker, contract = ibkr.get_ticker(symbol, timeout=3.0)
            price = float(ticker.last or ticker.close or 0.0)
            ibkr.cancel_market_data(contract)

            # LOD from today's 1m bars
            intra = ibkr.get_intraday_bars(symbol)
            lod   = float(intra["Low"].min()) if not intra.empty else 0.0
            stop  = lod * 0.99

            print(f"{ts()} {symbol} price=${price:.2f} lod=${lod:.2f} stop=${stop:.2f}")

            if price > 0 and lod > 0 and price <= stop:
                print(f"{ts()} STOP HIT: {symbol} ${price:.2f} <= ${stop:.2f}. Selling {qty}.")
                trade     = ibkr.place_order(symbol, "SELL", qty)
                status    = trade.orderStatus.status
                fill      = trade.orderStatus.avgFillPrice or 0
                order_id  = trade.order.orderId
                timestamp = datetime.now(ET).isoformat()
                print(f"{ts()} SOLD {symbol} fill=${fill} status={status}")

                trades_path = Path("trades.csv")
                write_header = not trades_path.exists()
                with open(trades_path, "a", newline="") as f:
                    writer = csv.writer(f)
                    if write_header:
                        writer.writerow(["timestamp_iso", "symbol", "side", "size", "fill_price", "order_id", "status"])
                    writer.writerow([timestamp, symbol, "SELL", qty, fill, order_id, status])

        except Exception as e:
            print(f"{ts()} Error checking {symbol}: {e}")

    try:
        ibkr.disconnect()
    except Exception:
        pass

    time.sleep(CHECK_INTERVAL)
