const axios = require('axios');
const https = require('https');
const config = require('./config');
const { getContainerInfo } = require('./docker');

// Store pour les statuts des apps
const appStatuses = new Map();

// Store pour les logs de déploiement
const deploymentLogs = [];
const MAX_DEPLOYMENT_LOGS = 50;

// Store pour les commits Gitea
const giteaCommits = new Map();

// Agent HTTPS qui ignore les certificats auto-signés
const httpsAgent = new https.Agent({ rejectUnauthorized: false });

// Au démarrage : marquer tous les déploiements "running" orphelins comme "failed"
// (ils ont été interrompus lors du dernier redémarrage du Dashboard)
function cleanupOrphanedDeployments() {
  const orphans = deploymentLogs.filter((l) => l.status === 'running');
  if (orphans.length > 0) {
    console.log(`[healthcheck] Nettoyage de ${orphans.length} déploiement(s) orphelin(s) au démarrage`);
    orphans.forEach((l) => {
      l.status = 'failed';
      l.message = 'Déploiement interrompu (redémarrage du Dashboard)';
      l.endedAt = new Date().toISOString();
    });
  }
}

/**
 * Vérifier la santé d'une URL
 */
async function checkUrl(url) {
  try {
    const start = Date.now();
    const response = await axios.get(url, {
      timeout: 10000,
      httpsAgent,
      validateStatus: (status) => status < 500,
    });
    const responseTime = Date.now() - start;
    return {
      online: true,
      statusCode: response.status,
      responseTime,
    };
  } catch (err) {
    return {
      online: false,
      statusCode: null,
      responseTime: null,
      error: err.message,
    };
  }
}

/**
 * Vérifier la santé d'une application
 */
async function checkApp(appConfig) {
  const result = {
    id: appConfig.id,
    name: appConfig.name,
    description: appConfig.description,
    urls: appConfig.urls,
    containerName: appConfig.containerName,
    lastCheck: new Date().toISOString(),
    status: 'unknown',
    container: null,
    health: {
      recette: null,
      prod: null,
    },
  };

  // Vérifier le conteneur Docker
  const containerInfo = await getContainerInfo(appConfig.containerName);
  result.container = containerInfo;

  // Health check recette
  if (appConfig.urls.recette) {
    result.health.recette = await checkUrl(appConfig.urls.recette);
  }

  // Health check prod
  if (appConfig.urls.prod) {
    result.health.prod = await checkUrl(appConfig.urls.prod);
  }

  // Déterminer le statut global
  if (!containerInfo || !containerInfo.running) {
    result.status = 'offline';
  } else if (result.health.recette && result.health.recette.online) {
    result.status = 'online';
  } else if (containerInfo.running) {
    result.status = 'error';
  } else {
    result.status = 'offline';
  }

  // Stocker le résultat
  appStatuses.set(appConfig.id, result);

  return result;
}

/**
 * Lancer les health checks pour toutes les apps
 */
async function checkAllApps() {
  const results = [];
  for (const app of config.apps) {
    const result = await checkApp(app);
    results.push(result);
  }
  return results;
}

/**
 * Ajouter un log de déploiement (retourne l'entrée créée avec son id)
 */
function addDeploymentLog(appId, log) {
  const entry = {
    id: Date.now().toString(),
    appId,
    timestamp: new Date().toISOString(),
    ...log,
  };
  deploymentLogs.unshift(entry);
  if (deploymentLogs.length > MAX_DEPLOYMENT_LOGS) {
    deploymentLogs.pop();
  }
  return entry;
}

/**
 * Mettre à jour un log de déploiement existant par son id
 * Permet de passer de "running" à "success" ou "failed" sans créer une nouvelle entrée
 */
function updateDeploymentLog(entryId, updates) {
  const entry = deploymentLogs.find((l) => l.id === entryId);
  if (entry) {
    Object.assign(entry, updates, { updatedAt: new Date().toISOString() });
    return entry;
  }
  return null;
}

/**
 * Récupérer les logs de déploiement
 */
function getDeploymentLogs(appId = null) {
  if (appId) {
    return deploymentLogs.filter((l) => l.appId === appId);
  }
  return deploymentLogs;
}

/**
 * Récupérer le statut d'une app
 */
function getAppStatus(appId) {
  return appStatuses.get(appId) || null;
}

/**
 * Récupérer tous les statuts
 */
function getAllStatuses() {
  return Array.from(appStatuses.values());
}

module.exports = {
  checkUrl,
  checkApp,
  checkAllApps,
  addDeploymentLog,
  updateDeploymentLog,
  getDeploymentLogs,
  getAppStatus,
  getAllStatuses,
  cleanupOrphanedDeployments,
  appStatuses,
  giteaCommits,
};
