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

/**
 * Récupérer la configuration d'une formation
 */
export async function getFormationConfig(formationId: number) {
  const db = await getDb();
  if (!db) return null;

  const results = await db
    .select({
      id: formations.id,
      nom: formations.nom,
      modeAttestation: formations.modeAttestation,
      modeEnvoi: formations.modeEnvoi,
    })
    .from(formations)
    .where(eq(formations.id, formationId))
    .limit(1);

  return results.length > 0 ? results[0] : null;
}

/**
 * Mettre à jour la configuration d'une formation
 */
export async function updateFormationConfig(
  formationId: number,
  modeAttestation: "auto" | "manuel",
  modeEnvoi: "auto" | "manuel"
) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  await db
    .update(formations)
    .set({
      modeAttestation,
      modeEnvoi,
      updatedAt: new Date(),
    })
    .where(eq(formations.id, formationId));

  return true;
}

/**
 * Récupérer toutes les attestations d'une formation avec les informations des apprenants
 */
export async function getAttestationsByFormation(formationId: number) {
  const db = await getDb();
  if (!db) return [];

  const results = await db
    .select({
      attestation: attestations,
      apprenant: apprenants,
      sequence: sequences,
    })
    .from(attestations)
    .innerJoin(inscriptions, eq(attestations.inscriptionId, inscriptions.id))
    .innerJoin(apprenants, eq(inscriptions.apprenantId, apprenants.id))
    .innerJoin(sequences, eq(inscriptions.sequenceId, sequences.id))
    .where(eq(sequences.formationId, formationId))
    .orderBy(desc(attestations.createdAt));

  return results;
}

/**
 * Uploader un document d'attestation pour un apprenant
 */
export async function uploadAttestationDocument(
  inscriptionId: number,
  documentUrl: string,
  documentS3Key: string,
  uploadedBy: number
) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  // Vérifier si une attestation existe déjà pour cette inscription
  const existing = await db
    .select({
      id: attestations.id,
      inscriptionId: attestations.inscriptionId,
      apprenantId: attestations.apprenantId,
      sequenceId: attestations.sequenceId,
    })
    .from(attestations)
    .where(eq(attestations.inscriptionId, inscriptionId))
    .limit(1);

  if (existing.length > 0) {
    // Mettre à jour l'attestation existante
    await db
      .update(attestations)
      .set({
        documentUrl,
        documentS3Key,
        uploadedBy,
        uploadedAt: new Date(),
      })
      .where(eq(attestations.inscriptionId, inscriptionId));

    return existing[0].id;
  } else {
    // Récupérer les informations de l'inscription
    const inscription = await db
      .select({
        apprenantId: inscriptions.apprenantId,
        sequenceId: inscriptions.sequenceId,
      })
      .from(inscriptions)
      .where(eq(inscriptions.id, inscriptionId))
      .limit(1);

    if (inscription.length === 0) {
      throw new Error("Inscription not found");
    }

    // Créer une nouvelle attestation
    const result = await db
      .insert(attestations)
      .values({
        inscriptionId,
        apprenantId: inscription[0].apprenantId,
        sequenceId: inscription[0].sequenceId,
        documentUrl,
        documentS3Key,
        uploadedBy,
        uploadedAt: new Date(),
      })
      .$returningId();

    return result[0].id;
  }
}

/**
 * Envoyer une attestation par email
 */
export async function markAttestationAsSent(attestationId: number) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  await db
    .update(attestations)
    .set({
      emailEnvoye: true,
      dateEnvoiEmail: new Date(),
    })
    .where(eq(attestations.id, attestationId));

  return true;
}

/**
 * Récupérer les apprenants d'une formation avec leur statut d'attestation
 */
export async function getApprenantsWithAttestationStatus(formationId: number) {
  const db = await getDb();
  if (!db) return [];

  const results = await db
    .select({
      // Apprenant
      apprenantId: apprenants.id,
      apprenantNom: apprenants.nom,
      apprenantPrenom: apprenants.prenom,
      apprenantEmail: apprenants.email,
      // Inscription
      inscriptionId: inscriptions.id,
      inscriptionSequenceId: inscriptions.sequenceId,
      // Sequence
      sequenceId: sequences.id,
      sequenceNom: sequences.nom,
      // Attestation
      attestationId: attestations.id,
      attestationDocumentUrl: attestations.documentUrl,
      attestationEmailEnvoye: attestations.emailEnvoye,
      attestationDateEnvoiEmail: attestations.dateEnvoiEmail,
    })
    .from(inscriptions)
    .innerJoin(apprenants, eq(inscriptions.apprenantId, apprenants.id))
    .innerJoin(sequences, eq(inscriptions.sequenceId, sequences.id))
    .leftJoin(attestations, eq(attestations.inscriptionId, inscriptions.id))
    .where(
      and(
        eq(sequences.formationId, formationId),
        eq(inscriptions.statut, "confirmee")
      )
    )
    .orderBy(apprenants.nom, apprenants.prenom);

  // Restructurer les résultats au format attendu
  return results.map(r => ({
    apprenant: {
      id: r.apprenantId,
      nom: r.apprenantNom,
      prenom: r.apprenantPrenom,
      email: r.apprenantEmail,
    },
    inscription: {
      id: r.inscriptionId,
      sequenceId: r.inscriptionSequenceId,
    },
    sequence: {
      id: r.sequenceId,
      nom: r.sequenceNom,
    },
    attestation: r.attestationId ? {
      id: r.attestationId,
      documentUrl: r.attestationDocumentUrl,
      emailEnvoye: r.attestationEmailEnvoye,
      dateEnvoiEmail: r.attestationDateEnvoiEmail,
    } : null,
  }));
}

/**
 * Supprimer un document d'attestation
 */
export async function deleteAttestationDocument(attestationId: number) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  await db
    .update(attestations)
    .set({
      documentUrl: null,
      documentS3Key: null,
      uploadedBy: null,
      uploadedAt: null,
      emailEnvoye: false,
      dateEnvoiEmail: null,
    })
    .where(eq(attestations.id, attestationId));

  return true;
}
