import asyncio
import logging
from datetime import datetime, time, timedelta
from typing import Optional

from .processar_ranking import ProcessarRankingJob

logger = logging.getLogger(__name__)


class RankingScheduler:
    def __init__(self, job: ProcessarRankingJob):
        self.job = job
        self.task: Optional[asyncio.Task] = None
        self.running = False

    async def _aguardar_proximo_horario(self, hora_alvo: int = 3) -> None:
        """
        Aguarda até a próxima ocorrência do horário alvo (padrão: 3h).
        """
        agora = datetime.now()
        proxima_execucao = agora.replace(hour=hora_alvo, minute=0, second=0, microsecond=0)

        if agora >= proxima_execucao:
            proxima_execucao += timedelta(days=1)

        segundos_ate_proxima = (proxima_execucao - agora).total_seconds()
        logger.info(f"Próxima execução do ranking: {proxima_execucao.strftime('%d/%m/%Y %H:%M:%S')}")

        await asyncio.sleep(segundos_ate_proxima)

    async def _loop_diario(self, hora_alvo: int = 3) -> None:
        """
        Loop infinito que executa o job diariamente no horário especificado.
        """
        while self.running:
            try:
                await self._aguardar_proximo_horario(hora_alvo)

                if not self.running:
                    break

                logger.info("Executando job de ranking automático")
                await self.job.executar(limpar_antes=True)

            except asyncio.CancelledError:
                logger.info("Scheduler cancelado")
                break
            except Exception as e:
                logger.error(f"Erro no scheduler: {e}")
                await asyncio.sleep(3600)

    async def iniciar(self, hora_alvo: int = 3) -> None:
        """
        Inicia o scheduler em background.
        O job rodará diariamente no horário especificado (padrão: 3h).
        """
        if self.running:
            return

        self.running = True
        self.task = asyncio.create_task(self._loop_diario(hora_alvo))
        await asyncio.sleep(0.1)
        logger.info(f"Scheduler do ranking iniciado: job rodará diariamente às {hora_alvo}h")

    def parar(self) -> None:
        """
        Para o scheduler.
        """
        self.running = False
        if self.task:
            self.task.cancel()
