package dev.lions.unionflow.server.scheduler;

import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.repository.OrganisationRepository;
import dev.lions.unionflow.server.service.reporting.RapportTrimestrielService;
import io.quarkus.scheduler.Scheduled;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.time.LocalDate;
import java.time.YearMonth;
import org.jboss.logging.Logger;

/**
 * Génération automatique des rapports trimestriels du Contrôleur Interne au début de chaque
 * trimestre (1er janvier / avril / juillet / octobre à 02:17), pour le trimestre précédent.
 *
 * <p>Override possible via configuration : {@code unionflow.reporting.trimestriel.cron}.
 *
 * @since 2026-04-25 (P2-NEW-3)
 */
@ApplicationScoped
public class RapportTrimestrielScheduler {

  private static final Logger LOG = Logger.getLogger(RapportTrimestrielScheduler.class);

  @Inject RapportTrimestrielService service;
  @Inject OrganisationRepository organisationRepository;

  /**
   * Cron Quarkus 6-fields : sec min hour dayOfMonth month dayOfWeek.
   * 1er jan/avr/jul/oct à 02:17. Minute non ronde pour étaler la charge sur la flotte.
   */
  @Scheduled(
      cron = "${unionflow.reporting.trimestriel.cron:0 17 2 1 1,4,7,10 ?}",
      identity = "rapport-trimestriel-controleur-interne",
      concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
  @Transactional
  void genererRapportsTrimestrePrecedent() {
    Trimestre tp = trimestrePrecedent(LocalDate.now());
    LOG.infof("[Scheduler] Démarrage génération rapports trimestriels — %d/T%d",
        tp.annee, tp.trimestre);

    int succes = 0;
    int erreurs = 0;
    for (Organisation org : organisationRepository.list("actif = true")) {
      try {
        service.genererRapport(org.getId(), tp.annee, tp.trimestre);
        succes++;
      } catch (IllegalStateException e) {
        // Rapport déjà SIGNE/ARCHIVE — normal en cas de relance
        LOG.debugf("Rapport %d/T%d org=%s déjà finalisé : %s",
            tp.annee, tp.trimestre, org.getId(), e.getMessage());
      } catch (Exception e) {
        erreurs++;
        LOG.errorf(e, "Échec génération rapport %d/T%d pour org=%s",
            tp.annee, tp.trimestre, org.getId());
      }
    }
    LOG.infof("[Scheduler] Rapports trimestriels %d/T%d : %d succès, %d erreurs",
        tp.annee, tp.trimestre, succes, erreurs);
  }

  /** Calcule (année, trimestre) du trimestre précédent à partir d'une date donnée. */
  static Trimestre trimestrePrecedent(LocalDate date) {
    YearMonth ymPrev = YearMonth.from(date).minusMonths(1);
    int trimestre = (ymPrev.getMonthValue() - 1) / 3 + 1;
    return new Trimestre(ymPrev.getYear(), trimestre);
  }

  record Trimestre(int annee, int trimestre) {}
}
