"""IB connection lifecycle shared by all live strategies."""

from __future__ import annotations

import asyncio
from typing import Any

from RenTech.live.platform_config import BrokerConfig


async def connect_ib(broker: BrokerConfig) -> Any:
    try:
        from ib_insync import IB
    except ImportError as e:
        raise ImportError("Install ib_insync: pip install ib_insync") from e

    ib = IB()
    await ib.connectAsync(
        broker.host,
        int(broker.port),
        clientId=int(broker.client_id),
        timeout=float(broker.connect_timeout_sec),
    )
    ib.reqMarketDataType(int(broker.market_data_type))
    return ib


async def disconnect_ib(ib: Any) -> None:
    if ib is not None and getattr(ib, "isConnected", lambda: False)():
        ib.disconnect()


async def ensure_positions_loaded(ib: Any, *, wait_sec: float = 1.5) -> None:
    """Request positions without nesting ``ib._run`` inside an already-running loop."""
    try:
        await ib.reqPositionsAsync()
    except Exception:
        # Fallback for older ib_insync builds
        ib.client.reqPositions()
        await asyncio.sleep(float(wait_sec))
        return
    await asyncio.sleep(min(0.25, float(wait_sec)))


async def ping_account(ib: Any) -> bool:
    """Lightweight health check (async-safe account summary)."""
    try:
        vals = await ib.accountSummaryAsync()
        return bool(vals)
    except Exception:
        return False


def has_pending_orders(ib: Any) -> bool:
    """True if IB reports any open trades or working orders."""
    try:
        open_trades = ib.openTrades()
        if open_trades:
            return True
    except Exception:
        pass
    try:
        open_orders = ib.openOrders()
        if open_orders:
            return True
    except Exception:
        pass
    return False
