import { eq, sql, and, gte, lte } from "drizzle-orm";
import { getDb } from "./db";
import { 
  questionnaires, 
  envoisQuestionnaires, 
  reponsesQuestionnaires,
  reponsesQuestions,
  questions,
  sequences,
  formations,
  formateurs
} from "../drizzle/schema";

/**
 * Statistiques de taux de réponse par formation
 */
export async function getStatsByFormation() {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  const results = await db
    .select({
      formationId: formations.id,
      formationNom: formations.nom,
      totalEnvois: sql<number>`COUNT(DISTINCT ${envoisQuestionnaires.id})`,
      totalReponses: sql<number>`SUM(CASE WHEN ${envoisQuestionnaires.dateReponse} IS NOT NULL THEN 1 ELSE 0 END)`,
    })
    .from(envoisQuestionnaires)
    .innerJoin(sequences, eq(envoisQuestionnaires.sequenceId, sequences.id))
    .innerJoin(formations, eq(sequences.formationId, formations.id))
    .groupBy(formations.id, formations.nom);

  return results.map(r => ({
    formationId: r.formationId,
    formationNom: r.formationNom,
    totalEnvois: Number(r.totalEnvois),
    totalReponses: Number(r.totalReponses),
    tauxReponse: Number(r.totalEnvois) > 0 
      ? Math.round((Number(r.totalReponses) / Number(r.totalEnvois)) * 100) 
      : 0
  }));
}

/**
 * Évolution temporelle des réponses (par mois)
 */
export async function getEvolutionTemporelle(startDate?: Date, endDate?: Date) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

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

  const results = await db
    .select({
      mois: sql<string>`DATE_FORMAT(${envoisQuestionnaires.dateEnvoi}, '%Y-%m')`,
      totalEnvois: sql<number>`COUNT(DISTINCT ${envoisQuestionnaires.id})`,
      totalReponses: sql<number>`SUM(CASE WHEN ${envoisQuestionnaires.dateReponse} IS NOT NULL THEN 1 ELSE 0 END)`,
    })
    .from(envoisQuestionnaires)
    .where(conditions.length > 0 ? and(...conditions) : undefined)
    .groupBy(sql`DATE_FORMAT(${envoisQuestionnaires.dateEnvoi}, '%Y-%m')`)
    .orderBy(sql`DATE_FORMAT(${envoisQuestionnaires.dateEnvoi}, '%Y-%m')`);

  return results.map(r => ({
    mois: r.mois,
    totalEnvois: Number(r.totalEnvois),
    totalReponses: Number(r.totalReponses),
    tauxReponse: Number(r.totalEnvois) > 0 
      ? Math.round((Number(r.totalReponses) / Number(r.totalEnvois)) * 100) 
      : 0
  }));
}

/**
 * Comparaison par formateur
 */
export async function getStatsByFormateur() {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  // Première requête : statistiques d'envois et réponses par formateur
  const statsEnvois = await db
    .select({
      formateurId: formateurs.id,
      formateurNom: formateurs.nom,
      totalEnvois: sql<number>`COUNT(DISTINCT ${envoisQuestionnaires.id})`,
      totalReponses: sql<number>`SUM(CASE WHEN ${envoisQuestionnaires.dateReponse} IS NOT NULL THEN 1 ELSE 0 END)`,
    })
    .from(envoisQuestionnaires)
    .innerJoin(sequences, eq(envoisQuestionnaires.sequenceId, sequences.id))
    .innerJoin(formateurs, eq(sequences.formateurId, formateurs.id))
    .groupBy(formateurs.id, formateurs.nom);

  // Pour chaque formateur, calculer la moyenne de satisfaction
  const results = await Promise.all(statsEnvois.map(async (stat) => {
    // Calculer la moyenne des réponses de type échelle pour ce formateur
    const satisfactionResult = await db
      .select({
        moyenne: sql<number>`AVG(CAST(${reponsesQuestions.reponseNumerique} AS DECIMAL(10,2)))`,
      })
      .from(reponsesQuestionnaires)
      .innerJoin(sequences, eq(reponsesQuestionnaires.sequenceId, sequences.id))
      .innerJoin(reponsesQuestions, eq(reponsesQuestionnaires.id, reponsesQuestions.reponseQuestionnaireId))
      .innerJoin(questions, eq(reponsesQuestions.questionId, questions.id))
      .where(
        and(
          eq(sequences.formateurId, stat.formateurId),
          eq(questions.typeQuestion, 'echelle')
        )
      );

    const moyenneSatisfaction = satisfactionResult[0]?.moyenne 
      ? Number(satisfactionResult[0].moyenne).toFixed(1) 
      : null;

    return {
      formateurId: stat.formateurId,
      formateurNom: stat.formateurNom || "Non spécifié",
      totalEnvois: Number(stat.totalEnvois),
      totalReponses: Number(stat.totalReponses),
      tauxReponse: Number(stat.totalEnvois) > 0 
        ? Math.round((Number(stat.totalReponses) / Number(stat.totalEnvois)) * 100) 
        : 0,
      moyenneSatisfaction
    };
  }));

  return results;
}

/**
 * Statistiques globales pour le tableau de bord
 */
export async function getStatsGlobales() {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  const results = await db
    .select({
      totalQuestionnaires: sql<number>`COUNT(DISTINCT ${questionnaires.id})`,
      totalEnvois: sql<number>`COUNT(DISTINCT ${envoisQuestionnaires.id})`,
      totalReponses: sql<number>`SUM(CASE WHEN ${envoisQuestionnaires.dateReponse} IS NOT NULL THEN 1 ELSE 0 END)`,
    })
    .from(questionnaires)
    .leftJoin(envoisQuestionnaires, eq(questionnaires.id, envoisQuestionnaires.questionnaireId));

  const stats = results[0];
  const totalEnvois = Number(stats.totalEnvois) || 0;
  const totalReponses = Number(stats.totalReponses) || 0;
  
  return {
    totalQuestionnaires: Number(stats.totalQuestionnaires) || 0,
    totalEnvois,
    totalReponses,
    tauxReponseGlobal: totalEnvois > 0 ? Number(((totalReponses / totalEnvois) * 100).toFixed(1)) : 0
  };
}
