import { eq, sql } from "drizzle-orm";
import { getDb } from "./db";
import { parametres, historiqueParametres } from "../drizzle/schema";

/**
 * Récupérer les paramètres de l'application
 * S'il n'y a pas de paramètres, en créer un avec les valeurs par défaut
 */
export async function getParametres() {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  const result = await db.select().from(parametres).limit(1);
  
  if (result.length === 0) {
    // Créer les paramètres par défaut
    await db.insert(parametres).values({
      urlPublique: "https://formations.itinova.org",
    });
    
    const newResult = await db.select().from(parametres).limit(1);
    return newResult[0];
  }
  
  return result[0];
}

/**
 * Mettre à jour les paramètres de l'application
 * Enregistre automatiquement l'historique des modifications
 */
export async function updateParametres(
  updates: Partial<{
    urlPublique: string;
    delaiExpirationQR: number;
    dureeValiditeToken: number;
    notificationsActives: boolean;
    envoiAutomatiqueAttestations: boolean;
  }>,
  userId: number,
  userName: string
) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  const params = await getParametres();
  
  // Enregistrer l'historique pour chaque champ modifié
  for (const [key, value] of Object.entries(updates)) {
    const oldValue = params[key as keyof typeof params];
    if (oldValue !== value) {
      await db.insert(historiqueParametres).values({
        userId,
        userName,
        champModifie: key,
        ancienneValeur: oldValue !== null && oldValue !== undefined ? String(oldValue) : null,
        nouvelleValeur: value !== null && value !== undefined ? String(value) : null,
      });
    }
  }
  
  // Mettre à jour les paramètres
  await db.update(parametres)
    .set(updates)
    .where(eq(parametres.id, params.id));
  
  return getParametres();
}

/**
 * Mettre à jour l'URL publique (fonction de compatibilité)
 */
export async function updateUrlPublique(urlPublique: string, userId?: number, userName?: string) {
  return updateParametres(
    { urlPublique },
    userId || 1,
    userName || "Système"
  );
}

/**
 * Récupérer l'historique des modifications des paramètres
 */
export async function getHistoriqueParametres(limit: number = 50) {
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  return db.select()
    .from(historiqueParametres)
    .orderBy(sql`${historiqueParametres.dateModification} DESC`)
    .limit(limit);
}

/**
 * Tester l'accessibilité d'une URL
 */
export async function testerUrl(url: string): Promise<{ accessible: boolean; message: string; statusCode?: number }> {
  try {
    // Vérifier le format de l'URL
    const urlObj = new URL(url);
    if (!['http:', 'https:'].includes(urlObj.protocol)) {
      return {
        accessible: false,
        message: "L'URL doit commencer par http:// ou https://"
      };
    }

    // Tenter une requête HEAD pour vérifier l'accessibilité
    const response = await fetch(url, {
      method: 'HEAD',
      signal: AbortSignal.timeout(5000), // Timeout de 5 secondes
    });

    return {
      accessible: response.ok,
      message: response.ok 
        ? "L'URL est accessible" 
        : `L'URL a retourné une erreur HTTP ${response.status}`,
      statusCode: response.status
    };
  } catch (error) {
    if (error instanceof TypeError && error.message.includes('Invalid URL')) {
      return {
        accessible: false,
        message: "Format d'URL invalide"
      };
    }
    
    return {
      accessible: false,
      message: `Erreur lors du test: ${error instanceof Error ? error.message : 'Erreur inconnue'}`
    };
  }
}
