"""实例实时监控采集调度。"""
from __future__ import annotations

import logging
from datetime import datetime, timedelta, timezone

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger

from app.database import async_session
from app.services.instance_real_data_service import (
    cleanup_old_real_data_snapshots,
    collect_instance_real_data,
    flush_real_data_buffer_to_db,
)

log = logging.getLogger("qycw.instance_real_data.scheduler")

COLLECT_INTERVAL_MINUTES = 3
INITIAL_DELAY_SECONDS = 20

_scheduler: AsyncIOScheduler | None = None


async def _job_collect() -> None:
    try:
        async with async_session() as session:
            written = await collect_instance_real_data(session)
            flushed = await flush_real_data_buffer_to_db(session)
            cleaned = await cleanup_old_real_data_snapshots(session)
        if written or flushed or cleaned:
            log.debug("instance real_data collect: cached=%s flushed=%s cleaned=%s", written, flushed, cleaned)
        else:
            log.debug("instance real_data collect: no items")
    except Exception:
        log.exception("instance real_data collect failed")


def start_instance_real_data_scheduler() -> None:
    global _scheduler
    if _scheduler is not None:
        return
    sched = AsyncIOScheduler(timezone="UTC")
    first_run = datetime.now(timezone.utc) + timedelta(seconds=INITIAL_DELAY_SECONDS)
    sched.add_job(
        _job_collect,
        IntervalTrigger(minutes=COLLECT_INTERVAL_MINUTES, jitter=20, start_date=first_run),
        id="instance_real_data_collect",
        next_run_time=first_run,
        max_instances=1,
        coalesce=True,
        misfire_grace_time=120,
    )
    sched.start()
    _scheduler = sched
    log.debug("instance real_data scheduler started: interval=%dm", COLLECT_INTERVAL_MINUTES)


def shutdown_instance_real_data_scheduler() -> None:
    global _scheduler
    if _scheduler is None:
        return
    _scheduler.shutdown(wait=False)
    _scheduler = None
