/**
 * TASKMATE - Backup System
 * ========================
 * Automatische Datenbank-Backups
 */

const fs = require('fs');
const path = require('path');
const logger = require('./logger');
const { encryptFile, decryptFile, secureDelete } = require('./encryption');

const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, '..', 'data');
const BACKUP_DIR = process.env.BACKUP_DIR || path.join(__dirname, '..', 'backups');
const DB_FILE = path.join(DATA_DIR, 'taskmate.db');

// Backup-Verzeichnis erstellen falls nicht vorhanden
if (!fs.existsSync(BACKUP_DIR)) {
  fs.mkdirSync(BACKUP_DIR, { recursive: true });
}


/**
 * Backup erstellen (mit einfacher Verschlüsselung)
 */
function createBackup() {
  try {
    if (!fs.existsSync(DB_FILE)) {
      logger.warn('Keine Datenbank zum Sichern gefunden');
      return null;
    }

    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const backupName = `backup_${timestamp}.db`;
    const encryptedName = `backup_${timestamp}.db.enc`;
    const backupPath = path.join(BACKUP_DIR, backupName);
    const encryptedPath = path.join(BACKUP_DIR, encryptedName);

    // 1. Normales Backup erstellen (für Kompatibilität)
    fs.copyFileSync(DB_FILE, backupPath);

    // 2. Verschlüsseltes Backup erstellen (zusätzlich)
    if (process.env.ENCRYPTION_KEY) {
      try {
        if (encryptFile(DB_FILE, encryptedPath)) {
          logger.info(`Verschlüsseltes Backup erstellt: ${encryptedName}`);
        } else {
          logger.warn('Verschlüsselung fehlgeschlagen, nur normales Backup erstellt');
        }
      } catch (encError) {
        logger.warn('Verschlüsselung fehlgeschlagen, nur normales Backup erstellt');
      }
    }

    // 3. WAL-Datei sichern falls vorhanden
    const walFile = DB_FILE + '-wal';
    if (fs.existsSync(walFile)) {
      fs.copyFileSync(walFile, backupPath + '-wal');
    }

    logger.info(`Backup erstellt: ${backupName}`);

    // Alte Backups aufräumen (behalte nur die letzten 30)
    cleanupOldBackups(30);

    return backupPath;
  } catch (error) {
    logger.error('Backup-Fehler:', { error: error.message });
    return null;
  }
}

/**
 * Alte Backups löschen (verschlüsselte)
 */
function cleanupOldBackups(keepCount = 30) {
  try {
    const files = fs.readdirSync(BACKUP_DIR)
      .filter(f => f.startsWith('backup_') && f.endsWith('.db.enc'))
      .sort()
      .reverse();

    const toDelete = files.slice(keepCount);

    toDelete.forEach(file => {
      const filePath = path.join(BACKUP_DIR, file);
      secureDelete(filePath);

      // Verschlüsselte WAL-Datei auch löschen falls vorhanden  
      const walPath = filePath + '-wal';
      if (fs.existsSync(walPath)) {
        secureDelete(walPath);
      }

      logger.info(`Altes Backup sicher gelöscht: ${file}`);
    });
  } catch (error) {
    logger.error('Fehler beim Aufräumen alter Backups:', { error: error.message });
  }
}

/**
 * Backup wiederherstellen (entschlüsselt)
 */
function restoreBackup(backupName) {
  try {
    const encryptedBackupPath = path.join(BACKUP_DIR, backupName);

    if (!fs.existsSync(encryptedBackupPath)) {
      throw new Error(`Backup nicht gefunden: ${backupName}`);
    }

    // Aktuelles DB verschlüsselt sichern bevor überschrieben wird
    if (fs.existsSync(DB_FILE)) {
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const safetyBackupPath = DB_FILE + `.before-restore-${timestamp}.enc`;
      if (!encryptFile(DB_FILE, safetyBackupPath)) {
        logger.warn('Sicherheitsbackup vor Wiederherstellung fehlgeschlagen');
      }
    }

    // Temporäre entschlüsselte Datei
    const tempRestorePath = path.join(BACKUP_DIR, `temp_restore_${Date.now()}.db`);
    
    // Backup entschlüsseln
    if (!decryptFile(encryptedBackupPath, tempRestorePath)) {
      throw new Error('Backup-Entschlüsselung fehlgeschlagen');
    }

    // Entschlüsselte DB kopieren
    fs.copyFileSync(tempRestorePath, DB_FILE);

    // WAL-Datei auch wiederherstellen falls vorhanden
    const encryptedWalBackup = encryptedBackupPath + '-wal';
    if (fs.existsSync(encryptedWalBackup)) {
      const tempWalPath = tempRestorePath + '-wal';
      if (decryptFile(encryptedWalBackup, tempWalPath)) {
        fs.copyFileSync(tempWalPath, DB_FILE + '-wal');
        secureDelete(tempWalPath);
      }
    }

    // Temporäre entschlüsselte Dateien sicher löschen
    secureDelete(tempRestorePath);

    logger.info(`Verschlüsseltes Backup wiederhergestellt: ${backupName}`);
    return true;
  } catch (error) {
    logger.error('Restore-Fehler:', { error: error.message });
    throw error;
  }
}

/**
 * Liste aller verschlüsselten Backups
 */
function listBackups() {
  try {
    const files = fs.readdirSync(BACKUP_DIR)
      .filter(f => f.startsWith('backup_') && f.endsWith('.db.enc'))
      .map(f => {
        const filePath = path.join(BACKUP_DIR, f);
        const stats = fs.statSync(filePath);
        return {
          name: f,
          size: stats.size,
          created: stats.birthtime
        };
      })
      .sort((a, b) => b.created - a.created);

    return files;
  } catch (error) {
    logger.error('Fehler beim Auflisten der Backups:', { error: error.message });
    return [];
  }
}

/**
 * Backup-Scheduler starten
 */
let schedulerInterval = null;

function startScheduler() {
  const intervalHours = parseInt(process.env.BACKUP_INTERVAL_HOURS) || 24;
  const intervalMs = intervalHours * 60 * 60 * 1000;

  // Erstes Backup nach 1 Minute
  setTimeout(() => {
    createBackup();
  }, 60 * 1000);

  // Regelmäßige Backups
  schedulerInterval = setInterval(() => {
    createBackup();
  }, intervalMs);

  logger.info(`Backup-Scheduler gestartet (alle ${intervalHours} Stunden)`);
}

/**
 * Backup-Scheduler stoppen
 */
function stopScheduler() {
  if (schedulerInterval) {
    clearInterval(schedulerInterval);
    schedulerInterval = null;
    logger.info('Backup-Scheduler gestoppt');
  }
}

module.exports = {
  createBackup,
  restoreBackup,
  listBackups,
  startScheduler,
  stopScheduler,
  cleanupOldBackups
};
