import { eq, and, desc, sql } from "drizzle-orm";
import { getDb } from "./db";
import {
  questionnaires,
  questions,
  reponsesQuestionnaires,
  reponsesQuestions,
  envoisQuestionnaires,
  type Questionnaire,
  type InsertQuestionnaire,
  type Question,
  type InsertQuestion,
  type ReponseQuestionnaire,
  type InsertReponseQuestionnaire,
  type ReponseQuestion,
  type InsertReponseQuestion,
  type EnvoiQuestionnaire,
  type InsertEnvoiQuestionnaire,
} from "../drizzle/schema";

// ========== QUESTIONNAIRES ==========

export async function getAllQuestionnaires() {
  const db = await getDb();
  if (!db) return [];
  return await db.select().from(questionnaires).orderBy(desc(questionnaires.createdAt));
}

export async function getQuestionnaireById(id: number) {
  const db = await getDb();
  if (!db) return null;
  const result = await db.select().from(questionnaires).where(eq(questionnaires.id, id)).limit(1);
  return result[0] || null;
}

export async function createQuestionnaire(data: InsertQuestionnaire) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  const result = await db.insert(questionnaires).values(data);
  return result[0].insertId;
}

export async function updateQuestionnaire(id: number, data: Partial<InsertQuestionnaire>) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  await db.update(questionnaires).set(data).where(eq(questionnaires.id, id));
}

export async function deleteQuestionnaire(id: number) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  // Supprimer d'abord les questions associées
  await db.delete(questions).where(eq(questions.questionnaireId, id));
  // Puis le questionnaire
  await db.delete(questionnaires).where(eq(questionnaires.id, id));
}

// ========== QUESTIONS ==========

export async function getQuestionsByQuestionnaireId(questionnaireId: number) {
  const db = await getDb();
  if (!db) return [];
  return await db
    .select()
    .from(questions)
    .where(eq(questions.questionnaireId, questionnaireId))
    .orderBy(questions.ordre);
}

export async function createQuestion(data: InsertQuestion) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  const result = await db.insert(questions).values(data);
  return result[0].insertId;
}

export async function updateQuestion(id: number, data: Partial<InsertQuestion>) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  await db.update(questions).set(data).where(eq(questions.id, id));
}

export async function deleteQuestion(id: number) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  await db.delete(questions).where(eq(questions.id, id));
}

// ========== RÉPONSES QUESTIONNAIRES ==========

export async function createReponseQuestionnaire(data: InsertReponseQuestionnaire) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  const result = await db.insert(reponsesQuestionnaires).values(data);
  return result[0].insertId;
}

export async function getReponseQuestionnaire(questionnaireId: number, apprenantId: number, sequenceId: number) {
  const db = await getDb();
  if (!db) return null;
  const result = await db
    .select()
    .from(reponsesQuestionnaires)
    .where(
      and(
        eq(reponsesQuestionnaires.questionnaireId, questionnaireId),
        eq(reponsesQuestionnaires.apprenantId, apprenantId),
        eq(reponsesQuestionnaires.sequenceId, sequenceId)
      )
    )
    .limit(1);
  return result[0] || null;
}

export async function updateReponseQuestionnaire(id: number, data: Partial<InsertReponseQuestionnaire>) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  await db.update(reponsesQuestionnaires).set(data).where(eq(reponsesQuestionnaires.id, id));
}

// ========== RÉPONSES QUESTIONS ==========

export async function createReponseQuestion(data: InsertReponseQuestion) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  const result = await db.insert(reponsesQuestions).values(data);
  return result[0].insertId;
}

export async function getReponsesByReponseQuestionnaireId(reponseQuestionnaireId: number) {
  const db = await getDb();
  if (!db) return [];
  return await db
    .select()
    .from(reponsesQuestions)
    .where(eq(reponsesQuestions.reponseQuestionnaireId, reponseQuestionnaireId));
}

// ========== ENVOIS QUESTIONNAIRES ==========

export async function createEnvoiQuestionnaire(data: InsertEnvoiQuestionnaire) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  const result = await db.insert(envoisQuestionnaires).values(data);
  return result[0].insertId;
}

export async function getEnvoiByToken(token: string) {
  const db = await getDb();
  if (!db) return null;
  const result = await db
    .select()
    .from(envoisQuestionnaires)
    .where(eq(envoisQuestionnaires.token, token))
    .limit(1);
  return result[0] || null;
}

export async function updateEnvoiQuestionnaire(id: number, data: Partial<InsertEnvoiQuestionnaire>) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");
  await db.update(envoisQuestionnaires).set(data).where(eq(envoisQuestionnaires.id, id));
}

export async function checkEnvoiExists(questionnaireId: number, apprenantId: number, sequenceId: number) {
  const db = await getDb();
  if (!db) return false;
  const result = await db
    .select()
    .from(envoisQuestionnaires)
    .where(
      and(
        eq(envoisQuestionnaires.questionnaireId, questionnaireId),
        eq(envoisQuestionnaires.apprenantId, apprenantId),
        eq(envoisQuestionnaires.sequenceId, sequenceId)
      )
    )
    .limit(1);
  return result.length > 0;
}

// ========== STATISTIQUES ==========

/**
 * Récupère les statistiques d'un questionnaire
 */
export async function getQuestionnaireStats(questionnaireId: number) {
  const db = await getDb();
  if (!db) return null;

  // Nombre total d'envois
  const envoisResult = await db
    .select({ count: sql<number>`count(*)` })
    .from(envoisQuestionnaires)
    .where(eq(envoisQuestionnaires.questionnaireId, questionnaireId));
  const totalEnvois = envoisResult[0]?.count || 0;

  // Nombre de réponses
  const reponsesResult = await db
    .select({ count: sql<number>`count(*)` })
    .from(reponsesQuestionnaires)
    .where(eq(reponsesQuestionnaires.questionnaireId, questionnaireId));
  const totalReponses = reponsesResult[0]?.count || 0;

  // Taux de réponse
  const tauxReponse = totalEnvois > 0 ? (totalReponses / totalEnvois) * 100 : 0;

  return {
    totalEnvois,
    totalReponses,
    tauxReponse: Math.round(tauxReponse * 10) / 10, // 1 décimale
  };
}

/**
 * Récupère les réponses détaillées d'un questionnaire pour analyse
 */
export async function getReponsesDetailleesQuestionnaire(questionnaireId: number) {
  const db = await getDb();
  if (!db) return [];

  const result = await db
    .select({
      reponseQuestionnaireId: reponsesQuestionnaires.id,
      apprenantId: reponsesQuestionnaires.apprenantId,
      sequenceId: reponsesQuestionnaires.sequenceId,
      dateReponse: reponsesQuestionnaires.dateReponse,
      questionId: reponsesQuestions.questionId,
      reponseNumerique: reponsesQuestions.reponseNumerique,
      reponseTexte: reponsesQuestions.reponseTexte,
    })
    .from(reponsesQuestionnaires)
    .leftJoin(
      reponsesQuestions,
      eq(reponsesQuestions.reponseQuestionnaireId, reponsesQuestionnaires.id)
    )
    .where(eq(reponsesQuestionnaires.questionnaireId, questionnaireId));

  return result;
}
