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.scheduler_log import log_task_result
from app.services import system_setting_service, task_center_service

log = logging.getLogger("qycw.upstream.actions.scheduler")

SCHEDULER_TICK_SECONDS = 30
INITIAL_DELAY_SECONDS = 60

_scheduler: AsyncIOScheduler | None = None
_last_sync_at: datetime | None = None


async def _job_sync_upstream_actions() -> None:
    global _last_sync_at
    try:
        async with async_session() as session:
            settings = await system_setting_service.get_business_settings(session)
            now = datetime.now(timezone.utc)
            if (
                _last_sync_at is not None
                and (now - _last_sync_at).total_seconds() < settings.task_sync_interval_seconds
            ):
                return
            _last_sync_at = now
            await session.commit()
        result = await task_center_service.run_task("upstream_action_sync", trigger_type="schedule")
        log_task_result(
            log,
            "upstream action scheduler",
            result,
            activity_keys=("success", "failed", "running", "errored"),
        )
    except Exception:
        log.exception("upstream action scheduler failed")


def start_upstream_action_scheduler() -> None:
    global _scheduler
    if _scheduler is not None:
        return
    scheduler = AsyncIOScheduler(timezone="UTC")
    first_run = datetime.now(timezone.utc) + timedelta(seconds=INITIAL_DELAY_SECONDS)
    scheduler.add_job(
        _job_sync_upstream_actions,
        IntervalTrigger(seconds=SCHEDULER_TICK_SECONDS, jitter=10, start_date=first_run),
        id="upstream_action_sync",
        next_run_time=first_run,
        max_instances=1,
        coalesce=True,
        misfire_grace_time=300,
    )
    scheduler.start()
    _scheduler = scheduler
    log.debug("upstream action scheduler started: tick=%ss", SCHEDULER_TICK_SECONDS)


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