import asyncio
import logging
import os
from datetime import datetime, timedelta
from typing import Any, Dict, Optional

from app.db.database import get_mongo_db
from app.v1.background.global_intraday import _get_global_zerodha_client
from app.v1.services.stocks_master import refresh_stocks_master

logger = logging.getLogger(__name__)

_TTL_HOURS_RAW = os.getenv("STOCKS_MASTER_REFRESH_TTL_HOURS")
_TTL_DAYS_RAW = os.getenv("STOCKS_MASTER_REFRESH_TTL_DAYS")

# Default: ~6 months. Override via env.
if _TTL_HOURS_RAW and str(_TTL_HOURS_RAW).strip():
    REFRESH_TTL_HOURS = int(_TTL_HOURS_RAW)
elif _TTL_DAYS_RAW and str(_TTL_DAYS_RAW).strip():
    REFRESH_TTL_HOURS = int(_TTL_DAYS_RAW) * 24
else:
    REFRESH_TTL_HOURS = 180 * 24
LOOP_INTERVAL_SECONDS = int(os.getenv("STOCKS_MASTER_REFRESH_LOOP_SECONDS", "3600"))


def _should_refresh(db, now: datetime) -> bool:
    try:
        doc = db["system_meta"].find_one({"key": "stocks_master_last_refreshed"}) or {}
        ts = doc.get("value") or doc.get("timestamp")
        if isinstance(ts, datetime):
            last = ts
        elif isinstance(ts, str):
            try:
                last = datetime.fromisoformat(ts.replace("Z", "+00:00")).replace(tzinfo=None)
            except Exception:
                last = None
        else:
            last = None
        if not last:
            return True
        return (now - last) >= timedelta(hours=max(1, REFRESH_TTL_HOURS))
    except Exception:
        return True


async def stocks_master_refresh_loop(interval_seconds: Optional[int] = None) -> None:
    interval_seconds = int(interval_seconds or LOOP_INTERVAL_SECONDS)
    interval_seconds = max(60, interval_seconds)

    while True:
        try:
            now = datetime.utcnow()
            for db in get_mongo_db():
                if not _should_refresh(db, now):
                    break

                zerodha = _get_global_zerodha_client(db)
                if not zerodha:
                    logger.warning("[StocksMaster] Global Zerodha client unavailable; skipping refresh")
                    break

                logger.info("[StocksMaster] Refreshing stocks master from Zerodha instruments")
                res = refresh_stocks_master(db=db, zerodha_client=zerodha, exchanges=["NSE"], allow_cache_write=True)
                logger.info(
                    "[StocksMaster] Done | inserted=%s updated=%s kept=%s instruments=%s",
                    res.get("inserted"),
                    res.get("updated"),
                    res.get("kept"),
                    res.get("instruments"),
                )
                break
        except Exception:
            logger.exception("[StocksMaster] Refresh loop error")

        await asyncio.sleep(interval_seconds)
