"""Фоновый контроль автозапуска/автоостановки парсинга по расписанию."""

from __future__ import annotations

import asyncio
import logging

from config import SCHEDULE_TICK_SEC, bot
from app.database.crud_filter import get_schedule_enabled_users
from app.schedule_utils import RUN_MODE_SCHEDULE, is_within_window, schedule_summary

_log = logging.getLogger(__name__)

_watcher_task: asyncio.Task | None = None


async def _notify(user_id: int, text: str) -> None:
    try:
        await bot.send_message(chat_id=user_id, text=text)
    except Exception as e:
        _log.debug("schedule notify failed user_id=%s: %s", user_id, e)


async def _tick_once() -> None:
    # Ленивый импорт, чтобы не плодить циклы при загрузке модулей
    from app.user.usermenu import (
        is_parsing_running_for_user,
        start_parsing_for_user,
        stop_parsing_for_user,
    )

    users = await get_schedule_enabled_users()
    if not users:
        return

    for settings in users:
        user_id = settings.get("user_id")
        if not user_id:
            continue
        if settings.get("run_mode") != RUN_MODE_SCHEDULE:
            continue

        inside = is_within_window(
            settings.get("work_from"),
            settings.get("work_to"),
            settings.get("work_days"),
        )
        running = is_parsing_running_for_user(int(user_id))

        if inside and not running:
            status = await start_parsing_for_user(
                int(user_id),
                source="schedule",
                restart_if_running=False,
            )
            if status == "started":
                _log.info("Автозапуск парсинга user_id=%s", user_id)
                await _notify(
                    int(user_id),
                    "⏰ <b>Автозапуск по расписанию</b>\n\n"
                    f"{schedule_summary(settings)}\n\n"
                    "Парсинг запущен. Остановить можно в «Мои задачи».",
                )
            elif status == "busy_other":
                _log.info(
                    "Автозапуск пропущен: Chrome занят (user_id=%s)",
                    user_id,
                )
            elif status == "no_filter":
                _log.warning("Автозапуск: нет фильтра user_id=%s", user_id)
        elif (not inside) and running:
            stopped = await stop_parsing_for_user(int(user_id), source="schedule")
            if stopped:
                _log.info("Автоостановка парсинга user_id=%s", user_id)
                await _notify(
                    int(user_id),
                    "🛑 <b>Автоостановка</b>\n"
                    "Время работы по расписанию закончилось.\n\n"
                    f"{schedule_summary(settings)}\n\n"
                    "Можно запустить вручную кнопкой «Запуск».",
                )


async def schedule_watcher_loop(stop_event: asyncio.Event | None = None) -> None:
    tick = max(15, int(SCHEDULE_TICK_SEC or 30))
    _log.info("Schedule watcher started (tick=%ss)", tick)
    # небольшой стартовый сдвиг, чтобы БД и polling успели подняться
    await asyncio.sleep(5)
    while True:
        if stop_event is not None and stop_event.is_set():
            break
        try:
            await _tick_once()
        except Exception:
            _log.exception("Schedule watcher tick failed")
        try:
            await asyncio.sleep(tick)
        except asyncio.CancelledError:
            break
    _log.info("Schedule watcher stopped")


def start_schedule_watcher() -> asyncio.Task:
    global _watcher_task
    if _watcher_task is not None and not _watcher_task.done():
        return _watcher_task
    _watcher_task = asyncio.create_task(schedule_watcher_loop(), name="schedule_watcher")
    return _watcher_task
