import { createError, readBody } from "h3"
import { getMysqlPool } from "~~/server/utils/mysql"
import { sendProjetAcademieEmails } from "~~/server/utils/mailer"

function normalizeValue(value) {
  return typeof value === "string" ? value.trim() : ""
}

function normalizeBoolean(value) {
  return value === true
}

function normalizePositiveInteger(value) {
  const number = Number(value)
  return Number.isInteger(number) && number > 0 ? number : null
}

function normalizeDiploma(diploma) {
  return {
    type: normalizeValue(diploma?.type),
    otherType: normalizeValue(diploma?.otherType),
    discipline: normalizeValue(diploma?.discipline),
    year: normalizeValue(diploma?.year),
    establishment: normalizeValue(diploma?.establishment),
  }
}

function isValidEmail(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}

function withTimeout(promise, delay, message) {
  return Promise.race([
    promise,
    new Promise((_, reject) => {
      setTimeout(() => reject(new Error(message)), delay)
    }),
  ])
}

function hasDiplomaData(diploma) {
  return Boolean(diploma.type || diploma.otherType || diploma.discipline || diploma.year || diploma.establishment)
}

function validateDiploma(diploma) {
  if (!hasDiplomaData(diploma)) {
    return true
  }

  if (!diploma.type || !diploma.discipline || !diploma.year || !diploma.establishment) {
    return false
  }

  if (diploma.type === "Autre" && !diploma.otherType) {
    return false
  }

  return true
}

export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  const payload = {
    lastName: normalizeValue(body?.lastName).toUpperCase(),
    firstName: normalizeValue(body?.firstName),
    gender: normalizeValue(body?.gender),
    birthDate: normalizeValue(body?.birthDate),
    birthPlace: normalizeValue(body?.birthPlace),
    nationality: normalizeValue(body?.nationality),
    email: normalizeValue(body?.email),
    phone: normalizeValue(body?.phone),
    address: normalizeValue(body?.address),
    city: normalizeValue(body?.city),
    postalCode: normalizeValue(body?.postalCode),
    country: normalizeValue(body?.country),
    instrument: normalizeValue(body?.instrument),
    previousAcademyParticipation: normalizeValue(body?.previousAcademyParticipation),
    previousAcademyParticipationCount: normalizePositiveInteger(body?.previousAcademyParticipationCount),
    trainingLevel: normalizeValue(body?.trainingLevel),
    otherTrainingLevel: normalizeValue(body?.otherTrainingLevel),
    conservatory: normalizeValue(body?.conservatory),
    otherConservatory: normalizeValue(body?.otherConservatory),
    teacherName: normalizeValue(body?.teacherName),
    diplomas: Array.isArray(body?.diplomas)
      ? body.diplomas.slice(0, 3).map(normalizeDiploma)
      : [],
    emergencyLastName: normalizeValue(body?.emergencyLastName),
    emergencyFirstName: normalizeValue(body?.emergencyFirstName),
    emergencyRelation: normalizeValue(body?.emergencyRelation),
    emergencyPhone: normalizeValue(body?.emergencyPhone),
    emergencyEmail: normalizeValue(body?.emergencyEmail),
    acceptRules: normalizeBoolean(body?.acceptRules),
  }

  while (payload.diplomas.length < 3) {
    payload.diplomas.push(normalizeDiploma({}))
  }

  if (
    !payload.lastName ||
    !payload.firstName ||
    !payload.gender ||
    !payload.birthDate ||
    !payload.birthPlace ||
    !payload.nationality ||
    !payload.email ||
    !payload.phone ||
    !payload.address ||
    !payload.city ||
    !payload.postalCode ||
    !payload.country ||
    !payload.instrument ||
    !payload.previousAcademyParticipation ||
    !payload.trainingLevel ||
    !payload.conservatory ||
    !payload.teacherName ||
    !payload.emergencyLastName ||
    !payload.emergencyFirstName ||
    !payload.emergencyRelation ||
    !payload.emergencyPhone ||
    !payload.emergencyEmail ||
    !payload.acceptRules
  ) {
    throw createError({
      statusCode: 400,
      statusMessage: "Tous les champs obligatoires doivent être remplis.",
    })
  }

  if (!isValidEmail(payload.email) || !isValidEmail(payload.emergencyEmail)) {
    throw createError({
      statusCode: 400,
      statusMessage: "Une adresse email n’est pas valide.",
    })
  }

  if (payload.previousAcademyParticipation === "oui" && !payload.previousAcademyParticipationCount) {
    throw createError({
      statusCode: 400,
      statusMessage: "Le nombre de participations est obligatoire.",
    })
  }

  if (payload.trainingLevel === "Autre" && !payload.otherTrainingLevel) {
    throw createError({
      statusCode: 400,
      statusMessage: "L’autre formation est obligatoire.",
    })
  }

  if (payload.conservatory === "Autre" && !payload.otherConservatory) {
    throw createError({
      statusCode: 400,
      statusMessage: "L’autre conservatoire est obligatoire.",
    })
  }

  if (!payload.diplomas.every(validateDiploma)) {
    throw createError({
      statusCode: 400,
      statusMessage: "Chaque diplôme renseigné doit être complet.",
    })
  }

  const db = getMysqlPool()
  const [diploma1, diploma2, diploma3] = payload.diplomas

  try {
    const [result] = await db.execute(
      `
        INSERT INTO academie_orchestre_candidatures (
          nom,
          prenom,
          genre,
          date_naissance,
          lieu_naissance,
          nationalite,
          email,
          telephone,
          adresse,
          ville,
          code_postal,
          pays_residence,
          instrument,
          deja_participe_academie,
          nombre_participations_academie,
          niveau_cycle_2026_2027,
          autre_formation,
          conservatoire_2026_2027,
          autre_conservatoire,
          professeur_instrument,
          diplome_1_type,
          diplome_1_autre_type,
          diplome_1_discipline,
          diplome_1_annee,
          diplome_1_etablissement,
          diplome_2_type,
          diplome_2_autre_type,
          diplome_2_discipline,
          diplome_2_annee,
          diplome_2_etablissement,
          diplome_3_type,
          diplome_3_autre_type,
          diplome_3_discipline,
          diplome_3_annee,
          diplome_3_etablissement,
          contact_urgence_nom,
          contact_urgence_prenom,
          contact_urgence_lien,
          contact_urgence_telephone,
          contact_urgence_email,
          reglement_accepte
        )
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      `,
      [
        payload.lastName,
        payload.firstName,
        payload.gender,
        payload.birthDate,
        payload.birthPlace,
        payload.nationality,
        payload.email,
        payload.phone,
        payload.address,
        payload.city,
        payload.postalCode,
        payload.country,
        payload.instrument,
        payload.previousAcademyParticipation,
        payload.previousAcademyParticipationCount,
        payload.trainingLevel,
        payload.otherTrainingLevel,
        payload.conservatory,
        payload.otherConservatory,
        payload.teacherName,
        diploma1.type,
        diploma1.otherType,
        diploma1.discipline,
        diploma1.year,
        diploma1.establishment,
        diploma2.type,
        diploma2.otherType,
        diploma2.discipline,
        diploma2.year,
        diploma2.establishment,
        diploma3.type,
        diploma3.otherType,
        diploma3.discipline,
        diploma3.year,
        diploma3.establishment,
        payload.emergencyLastName,
        payload.emergencyFirstName,
        payload.emergencyRelation,
        payload.emergencyPhone,
        payload.emergencyEmail,
        payload.acceptRules,
      ]
    )

    let emailsSent = false

    try {
      emailsSent = await withTimeout(
        sendProjetAcademieEmails(payload),
        15000,
        "Délai dépassé pour l'envoi email projet-academie."
      )
    } catch (mailError) {
      console.error("Erreur envoi email projet-academie:", mailError)
    }

    return {
      ok: true,
      id: result.insertId,
      emailsSent,
    }
  } catch (error) {
    console.error("Erreur API projet-academie:", error)

    throw createError({
      statusCode: 500,
      statusMessage: "Impossible d’enregistrer la candidature pour le moment.",
    })
  }
})
