#!/usr/bin/env tsx
/**
 * Script de gestion des sauvegardes via CLI
 * Usage: tsx scripts/backup-manager.ts [command] [options]
 */

import {
  backupService,
  BackupConfig,
} from '../src/services/data-management/backup';
import { backupScheduler } from '../src/services/data-management/backup-scheduler';
import { formatDateForDisplay } from '../src/lib/date-utils';

interface CliOptions {
  command: string;
  filename?: string;
  config?: Partial<BackupConfig>;
  force?: boolean;
  help?: boolean;
}

class BackupManagerCLI {
  private printHelp(): void {
    console.log(`
🔧 TowerControl Backup Manager

COMMANDES:
  create [--force]          Créer une nouvelle sauvegarde (--force pour ignorer la détection de changements)
  list                      Lister toutes les sauvegardes
  delete <filename>         Supprimer une sauvegarde
  restore <filename>        Restaurer une sauvegarde
  verify                    Vérifier l'intégrité de la base
  config                    Afficher la configuration
  config-set <key=value>    Modifier la configuration
  scheduler-start           Démarrer le planificateur
  scheduler-stop            Arrêter le planificateur
  scheduler-status          Statut du planificateur
  help                      Afficher cette aide

EXEMPLES:
  tsx backup-manager.ts create
  tsx backup-manager.ts create --force
  tsx backup-manager.ts list
  tsx backup-manager.ts delete towercontrol_2025-01-15T10-30-00-000Z.db
  tsx backup-manager.ts restore towercontrol_2025-01-15T10-30-00-000Z.db.gz
  tsx backup-manager.ts config-set interval=daily
  tsx backup-manager.ts config-set maxBackups=10
  tsx backup-manager.ts verify

OPTIONS:
  --force                   Forcer l'action sans confirmation
  --help                    Afficher l'aide
`);
  }

  private parseArgs(args: string[]): CliOptions {
    const options: CliOptions = {
      command: args[0] || 'help',
    };

    for (let i = 1; i < args.length; i++) {
      const arg = args[i];

      if (arg === '--force') {
        options.force = true;
      } else if (arg === '--help') {
        options.help = true;
      } else if (!options.filename && !arg.startsWith('--')) {
        options.filename = arg;
      }
    }

    return options;
  }

  private async confirmAction(
    message: string,
    force?: boolean
  ): Promise<boolean> {
    if (force) return true;

    // Simulation d'une confirmation (en CLI réel, utiliser readline)
    console.log(`⚠️  ${message}`);
    console.log('✅ Action confirmée (--force activé ou mode auto)');
    return true;
  }

  private formatFileSize(bytes: number): string {
    const units = ['B', 'KB', 'MB', 'GB'];
    let size = bytes;
    let unitIndex = 0;

    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024;
      unitIndex++;
    }

    return `${size.toFixed(1)} ${units[unitIndex]}`;
  }

  private formatDate(date: Date): string {
    return formatDateForDisplay(date, 'DISPLAY_LONG');
  }

  async run(args: string[]): Promise<void> {
    const options = this.parseArgs(args);

    if (options.help || options.command === 'help') {
      this.printHelp();
      return;
    }

    try {
      switch (options.command) {
        case 'create':
          await this.createBackup(options.force || false);
          break;

        case 'list':
          await this.listBackups();
          break;

        case 'delete':
          if (!options.filename) {
            console.error('❌ Nom de fichier requis pour la suppression');
            process.exit(1);
          }
          await this.deleteBackup(options.filename, options.force);
          break;

        case 'restore':
          if (!options.filename) {
            console.error('❌ Nom de fichier requis pour la restauration');
            process.exit(1);
          }
          await this.restoreBackup(options.filename, options.force);
          break;

        case 'verify':
          await this.verifyDatabase();
          break;

        case 'config':
          await this.showConfig();
          break;

        case 'config-set':
          if (!options.filename) {
            console.error('❌ Configuration requise (format: key=value)');
            process.exit(1);
          }
          await this.setConfig(options.filename);
          break;

        case 'scheduler-start':
          await this.startScheduler();
          break;

        case 'scheduler-stop':
          await this.stopScheduler();
          break;

        case 'scheduler-status':
          await this.schedulerStatus();
          break;

        default:
          console.error(`❌ Commande inconnue: ${options.command}`);
          this.printHelp();
          process.exit(1);
      }
    } catch (error) {
      console.error(`❌ Erreur:`, error);
      process.exit(1);
    }
  }

  private async createBackup(force: boolean = false): Promise<void> {
    console.log("🔄 Création d'une sauvegarde...");
    const result = await backupService.createBackup('manual', force);

    if (result === null) {
      console.log(
        '⏭️ Sauvegarde sautée: Aucun changement détecté depuis la dernière sauvegarde'
      );
      console.log(
        '   💡 Utilisez --force pour créer une sauvegarde malgré tout'
      );
      return;
    }

    if (result.status === 'success') {
      console.log(`✅ Sauvegarde créée: ${result.filename}`);
      console.log(`   Taille: ${this.formatFileSize(result.size)}`);
      if (result.databaseHash) {
        console.log(`   Hash: ${result.databaseHash.substring(0, 12)}...`);
      }
    } else {
      console.error(`❌ Échec de la sauvegarde: ${result.error}`);
      process.exit(1);
    }
  }

  private async listBackups(): Promise<void> {
    console.log('📋 Liste des sauvegardes:\n');
    const backups = await backupService.listBackups();

    if (backups.length === 0) {
      console.log('   Aucune sauvegarde disponible');
      return;
    }

    console.log(
      `${'Nom'.padEnd(40)} ${'Taille'.padEnd(10)} ${'Type'.padEnd(12)} ${'Date'}`
    );
    console.log('─'.repeat(80));

    for (const backup of backups) {
      const name = backup.filename.padEnd(40);
      const size = this.formatFileSize(backup.size).padEnd(10);
      const type = (
        backup.type === 'manual' ? 'Manuelle' : 'Automatique'
      ).padEnd(12);
      const date = this.formatDate(backup.createdAt);

      console.log(`${name} ${size} ${type} ${date}`);
    }

    console.log(`\n📊 Total: ${backups.length} sauvegarde(s)`);
  }

  private async deleteBackup(filename: string, force?: boolean): Promise<void> {
    const confirmed = await this.confirmAction(
      `Supprimer la sauvegarde "${filename}" ?`,
      force
    );

    if (!confirmed) {
      console.log('❌ Suppression annulée');
      return;
    }

    await backupService.deleteBackup(filename);
    console.log(`✅ Sauvegarde supprimée: ${filename}`);
  }

  private async restoreBackup(
    filename: string,
    force?: boolean
  ): Promise<void> {
    const confirmed = await this.confirmAction(
      `Restaurer la base de données depuis "${filename}" ? ATTENTION: Cela remplacera toutes les données actuelles !`,
      force
    );

    if (!confirmed) {
      console.log('❌ Restauration annulée');
      return;
    }

    console.log('🔄 Restauration en cours...');
    await backupService.restoreBackup(filename);
    console.log(`✅ Base de données restaurée depuis: ${filename}`);
  }

  private async verifyDatabase(): Promise<void> {
    console.log("🔍 Vérification de l'intégrité de la base...");
    await backupService.verifyDatabaseHealth();
    console.log('✅ Base de données vérifiée avec succès');
  }

  private async showConfig(): Promise<void> {
    const config = await backupService.getConfig();
    const status = backupScheduler.getStatus();

    console.log('⚙️  Configuration des sauvegardes:\n');
    console.log(
      `   Activé:              ${config.enabled ? '✅ Oui' : '❌ Non'}`
    );
    console.log(`   Fréquence:           ${config.interval}`);
    console.log(`   Max sauvegardes:     ${config.maxBackups}`);
    console.log(
      `   Compression:         ${config.compression ? '✅ Oui' : '❌ Non'}`
    );
    console.log(`   Chemin:              ${config.backupPath}`);
    console.log(`\n📊 Statut du planificateur:`);
    console.log(
      `   En cours:            ${status.isRunning ? '✅ Oui' : '❌ Non'}`
    );
    console.log(
      `   Prochaine:           ${status.nextBackup ? this.formatDate(status.nextBackup) : 'Non planifiée'}`
    );
  }

  private async setConfig(configString: string): Promise<void> {
    const [key, value] = configString.split('=');

    if (!key || !value) {
      console.error('❌ Format invalide. Utilisez: key=value');
      process.exit(1);
    }

    const newConfig: Partial<BackupConfig> = {};

    switch (key) {
      case 'enabled':
        newConfig.enabled = value.toLowerCase() === 'true';
        break;
      case 'interval':
        if (!['hourly', 'daily', 'weekly'].includes(value)) {
          console.error(
            '❌ Interval invalide. Utilisez: hourly, daily, ou weekly'
          );
          process.exit(1);
        }
        newConfig.interval = value as BackupConfig['interval'];
        break;
      case 'maxBackups':
        const maxBackups = parseInt(value);
        if (isNaN(maxBackups) || maxBackups < 1) {
          console.error('❌ maxBackups doit être un nombre positif');
          process.exit(1);
        }
        newConfig.maxBackups = maxBackups;
        break;
      case 'compression':
        newConfig.compression = value.toLowerCase() === 'true';
        break;
      default:
        console.error(`❌ Clé de configuration inconnue: ${key}`);
        process.exit(1);
    }

    backupService.updateConfig(newConfig);
    console.log(`✅ Configuration mise à jour: ${key} = ${value}`);

    // Redémarrer le scheduler si nécessaire
    if (key === 'enabled' || key === 'interval') {
      backupScheduler.restart();
      console.log('🔄 Planificateur redémarré avec la nouvelle configuration');
    }
  }

  private async startScheduler(): Promise<void> {
    backupScheduler.start();
    console.log('✅ Planificateur de sauvegarde démarré');
  }

  private async stopScheduler(): Promise<void> {
    backupScheduler.stop();
    console.log('🛑 Planificateur de sauvegarde arrêté');
  }

  private async schedulerStatus(): Promise<void> {
    const status = backupScheduler.getStatus();

    console.log('📊 Statut du planificateur:\n');
    console.log(
      `   État:                ${status.isRunning ? '✅ Actif' : '❌ Arrêté'}`
    );
    console.log(
      `   Activé:              ${status.isEnabled ? '✅ Oui' : '❌ Non'}`
    );
    console.log(`   Fréquence:           ${status.interval}`);
    console.log(
      `   Prochaine:           ${status.nextBackup ? this.formatDate(status.nextBackup) : 'Non planifiée'}`
    );
    console.log(`   Max sauvegardes:     ${status.maxBackups}`);
  }
}

// Exécution du script
if (require.main === module) {
  const cli = new BackupManagerCLI();
  const args = process.argv.slice(2);

  cli.run(args).catch((error) => {
    console.error('❌ Erreur fatale:', error);
    process.exit(1);
  });
}

export { BackupManagerCLI };
