/**
 * Requêtes analytiques pour le tableau de bord
 */

import { eq, sql, and, gte, lte, desc } from "drizzle-orm";
import { getDb } from "./db";
import { inscriptions, sequences, apprenants, datesFormation, formations } from "../drizzle/schema";

/**
 * Récupère les statistiques d'inscriptions par mois
 * @param startDate - Date de début de la période
 * @param endDate - Date de fin de la période
 */
export async function getInscriptionsByMonth(startDate?: Date, endDate?: Date) {
  const db = await getDb();
  if (!db) return [];

  const conditions = [];
  if (startDate) {
    conditions.push(gte(inscriptions.dateInscription, startDate));
  }
  if (endDate) {
    conditions.push(lte(inscriptions.dateInscription, endDate));
  }

  const result = await db
    .select({
      mois: sql<string>`DATE_FORMAT(${inscriptions.dateInscription}, '%Y-%m')`,
      total: sql<number>`COUNT(*)`,
      confirmees: sql<number>`SUM(CASE WHEN ${inscriptions.statut} = 'confirmee' THEN 1 ELSE 0 END)`,
      listeAttente: sql<number>`SUM(CASE WHEN ${inscriptions.statut} = 'liste_attente' THEN 1 ELSE 0 END)`,
      annulees: sql<number>`SUM(CASE WHEN ${inscriptions.statut} = 'annulee' THEN 1 ELSE 0 END)`,
    })
    .from(inscriptions)
    .where(conditions.length > 0 ? and(...conditions) : undefined)
    .groupBy(sql`DATE_FORMAT(${inscriptions.dateInscription}, '%Y-%m')`)
    .orderBy(sql`DATE_FORMAT(${inscriptions.dateInscription}, '%Y-%m')`);

  return result;
}

/**
 * Récupère le taux de remplissage des séquences par mois
 */
export async function getTauxRemplissageByMonth() {
  const db = await getDb();
  if (!db) return [];

  const result = await db
    .select({
      mois: sql<string>`DATE_FORMAT(${sequences.createdAt}, '%Y-%m')`,
      capaciteTotale: sql<number>`SUM(${sequences.capaciteMax})`,
      inscritsConfirmes: sql<number>`SUM(
        (SELECT COUNT(*) 
         FROM ${inscriptions} 
         WHERE ${inscriptions.sequenceId} = ${sequences.id} 
         AND ${inscriptions.statut} = 'confirmee')
      )`,
      tauxRemplissage: sql<number>`ROUND(
        (SUM(
          (SELECT COUNT(*) 
           FROM ${inscriptions} 
           WHERE ${inscriptions.sequenceId} = ${sequences.id} 
           AND ${inscriptions.statut} = 'confirmee')
        ) / SUM(${sequences.capaciteMax})) * 100, 
        2
      )`,
    })
    .from(sequences)
    .groupBy(sql`DATE_FORMAT(${sequences.createdAt}, '%Y-%m')`)
    .orderBy(sql`DATE_FORMAT(${sequences.createdAt}, '%Y-%m')`);

  return result;
}

/**
 * Récupère les statistiques de participation par établissement
 */
export async function getParticipationByEtablissement() {
  const db = await getDb();
  if (!db) return [];

  const result = await db
    .select({
      codeEtablissement: apprenants.codeEtablissement,
      totalApprenants: sql<number>`COUNT(DISTINCT ${apprenants.id})`,
      totalInscriptions: sql<number>`COUNT(${inscriptions.id})`,
      inscriptionsConfirmees: sql<number>`SUM(CASE WHEN ${inscriptions.statut} = 'confirmee' THEN 1 ELSE 0 END)`,
      inscriptionsListeAttente: sql<number>`SUM(CASE WHEN ${inscriptions.statut} = 'liste_attente' THEN 1 ELSE 0 END)`,
      inscriptionsAnnulees: sql<number>`SUM(CASE WHEN ${inscriptions.statut} = 'annulee' THEN 1 ELSE 0 END)`,
    })
    .from(apprenants)
    .leftJoin(inscriptions, eq(apprenants.id, inscriptions.apprenantId))
    .groupBy(apprenants.codeEtablissement)
    .orderBy(desc(sql<number>`COUNT(${inscriptions.id})`));

  return result;
}

/**
 * Récupère les statistiques globales du tableau de bord
 */
export async function getGlobalStats() {
  const db = await getDb();
  if (!db) return null;

  const [stats] = await db
    .select({
      totalFormations: sql<number>`(SELECT COUNT(*) FROM ${formations} WHERE ${formations.actif} = 1)`,
      totalSequences: sql<number>`(SELECT COUNT(*) FROM ${sequences})`,
      sequencesOuvertes: sql<number>`(SELECT COUNT(*) FROM ${sequences} WHERE ${sequences.statut} = 'ouverte')`,
      totalApprenants: sql<number>`(SELECT COUNT(*) FROM ${apprenants})`,
      totalInscriptions: sql<number>`(SELECT COUNT(*) FROM ${inscriptions})`,
      inscriptionsConfirmees: sql<number>`(SELECT COUNT(*) FROM ${inscriptions} WHERE ${inscriptions.statut} = 'confirmee')`,
      inscriptionsListeAttente: sql<number>`(SELECT COUNT(*) FROM ${inscriptions} WHERE ${inscriptions.statut} = 'liste_attente')`,
      tauxRemplissageMoyen: sql<number>`ROUND(
        (SELECT COUNT(*) FROM ${inscriptions} WHERE ${inscriptions.statut} = 'confirmee') / 
        (SELECT SUM(${sequences.capaciteMax}) FROM ${sequences}) * 100,
        2
      )`,
    })
    .from(sql`dual`);

  return stats;
}

/**
 * Récupère les statistiques de participation par fonction
 */
export async function getParticipationByFonction() {
  const db = await getDb();
  if (!db) return [];

  const result = await db
    .select({
      fonction: apprenants.fonction,
      totalApprenants: sql<number>`COUNT(DISTINCT ${apprenants.id})`,
      totalInscriptions: sql<number>`COUNT(${inscriptions.id})`,
      inscriptionsConfirmees: sql<number>`SUM(CASE WHEN ${inscriptions.statut} = 'confirmee' THEN 1 ELSE 0 END)`,
    })
    .from(apprenants)
    .leftJoin(inscriptions, eq(apprenants.id, inscriptions.apprenantId))
    .groupBy(apprenants.fonction)
    .orderBy(desc(sql<number>`COUNT(${inscriptions.id})`));

  return result;
}
