import asyncio
import logging
from datetime import datetime

from app.db.database import get_mongo_db
from app.v1.services.paper_trading import close_paper_trades_for_intraday_time_exit
from app.v1.utils.market_time import (
    backend_market_window,
    format_window,
    is_backend_market_hours,
    local_now,
    local_time_str,
    next_backend_market_open_local,
    seconds_until,
)


logger = logging.getLogger(__name__)

_INTRADAY_EXIT_LOCK = asyncio.Lock()


async def paper_intraday_exit_loop(interval_seconds: int = 60) -> None:
    """Force-close OPEN paper trades at PAPER_TRADE_END.

    This runs only during the backend market window (BACKEND_MARKET_START/END).
    """

    await asyncio.sleep(5)
    logger.info("[PaperIntradayExit] Loop started (interval=%ss)", int(interval_seconds))

    while True:
        try:
            if not is_backend_market_hours():
                nxt = next_backend_market_open_local()
                logger.info(
                    "[PaperIntradayExit] Backend skipped due to time | now=%s | window=%s",
                    local_time_str(),
                    format_window(backend_market_window()),
                )
                if nxt is not None:
                    await asyncio.sleep(seconds_until(local_now(), nxt))
                else:
                    await asyncio.sleep(interval_seconds)
                continue

            if _INTRADAY_EXIT_LOCK.locked():
                await asyncio.sleep(interval_seconds)
                continue

            async with _INTRADAY_EXIT_LOCK:
                now = datetime.utcnow()

                db_gen = get_mongo_db()
                db = next(db_gen)
                try:
                    res = close_paper_trades_for_intraday_time_exit(db, now_utc=now)
                finally:
                    try:
                        db_gen.close()
                    except Exception:
                        pass

                if res.get("ran") and int(res.get("closed") or 0) > 0:
                    logger.info(
                        "[PaperIntradayExit] Paper trade force-closed at 15:00 | closed=%s scanned=%s",
                        res.get("closed"),
                        res.get("scanned"),
                    )
        except Exception:
            logger.exception("[PaperIntradayExit] Unexpected error")

        await asyncio.sleep(interval_seconds)
