import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { LembretesService } from '../lembretes/lembretes.service';
import { SyncService } from '../sync/sync.service';

/**
 * Agendador dos jobs recorrentes.
 *
 * `JOBS_HABILITADOS=false` desliga tudo — os testes e2e chamam os serviços
 * diretamente e não devem competir com o cron pelo mesmo banco.
 *
 * ⚠️ Hospedagem que hiberna por inatividade **para estes jobs em silêncio**, e
 * aí o prazo fecha na hora errada sem nenhum erro aparecer. É o requisito de
 * infra mais fácil de errar em free tier (PP-10 OPS-1).
 */
@Injectable()
export class JobsService {
  private readonly log = new Logger(JobsService.name);

  constructor(
    private readonly sync: SyncService,
    private readonly lembretes: LembretesService,
  ) {}

  private get habilitado(): boolean {
    return process.env.JOBS_HABILITADOS !== 'false';
  }

  /**
   * Sincroniza com a fonte de dados. De hora em hora: ~24 requisições/dia cabe
   * folgado no limite de 10/min do tier gratuito.
   */
  @Cron(CronExpression.EVERY_HOUR, { name: 'sincronizar-fonte' })
  async sincronizar(): Promise<void> {
    if (!this.habilitado) return;
    try {
      const r = await this.sync.sincronizar('BSA');
      if (r.ignorada) {
        // A execução anterior ainda está rodando. Se isto aparecer sempre, o
        // intervalo do cron está curto demais para o tempo da sincronização.
        this.log.warn(
          'sincronização anterior ainda em andamento — ciclo ignorado',
        );
        return;
      }
      if (r.falhou) {
        this.log.warn('sincronização falhou — dado existente preservado');
        return;
      }
      if (r.horariosAlterados || r.placaresAlterados || r.palpitesApurados) {
        this.log.log(
          `sync: ${r.horariosAlterados} horário(s), ${r.placaresAlterados} placar(es), ` +
            `${r.palpitesApurados} palpite(s) apurado(s), ${r.correcoesAplicadas} correção(ões)`,
        );
      }
    } catch (erro) {
      // Job que morre por exceção para de rodar em silêncio — logar é o mínimo.
      this.log.error(`sincronização lançou exceção: ${String(erro)}`);
    }
  }

  /**
   * Lembretes de prazo. A cada 10 minutos: a janela de aviso é de ~2h, então
   * este intervalo dá folga sem spammar.
   */
  @Cron('*/10 * * * *', { name: 'lembretes-de-prazo' })
  async lembrar(): Promise<void> {
    if (!this.habilitado) return;
    try {
      await this.lembretes.dispararPendentes();
    } catch (erro) {
      this.log.error(`lembretes lançaram exceção: ${String(erro)}`);
    }
  }
}
