const express = require('express');
const router = express.Router();
const { adminAuth } = require('../middleware/auth');
const { databaseBackupService } = require('../services/databaseBackup');
const { db } = require('../database/db');
const logger = require('../utils/logger');

// All routes require admin authentication
router.use(adminAuth);

/**
 * Get database backup status and configuration
 */
router.get('/status', async (req, res) => {
  try {
    // Get configuration
    const config = await databaseBackupService.getBackupConfig();
    
    // Get recent backup history
    const history = await databaseBackupService.getBackupHistory(10);
    
    // Get current progress if running
    const progress = databaseBackupService.getProgress();
    
    // Calculate health status
    const lastBackup = history[0];
    const isHealthy = lastBackup && lastBackup.status === 'completed' && 
      new Date(lastBackup.completed_at) > new Date(Date.now() - 48 * 60 * 60 * 1000); // Within 48 hours
    
    res.json({
      config,
      isRunning: databaseBackupService.isRunning,
      isHealthy,
      currentProgress: progress,
      lastBackup,
      recentBackups: history,
      dbType: databaseBackupService.dbType
    });
  } catch (error) {
    logger.error('Failed to get database backup status:', error);
    res.status(500).json({ error: 'Failed to get backup status' });
  }
});

/**
 * Update database backup configuration
 */
router.put('/config', async (req, res) => {
  try {
    const allowedSettings = [
      'database_backup_enabled',
      'database_backup_schedule',
      'database_backup_destination_path',
      'database_backup_compress',
      'database_backup_validate_integrity',
      'database_backup_include_checksums',
      'database_backup_retention_days',
      'database_backup_email_on_failure',
      'database_backup_email_on_success'
    ];
    
    const updates = [];
    
    for (const [key, value] of Object.entries(req.body)) {
      if (allowedSettings.includes(key)) {
        // Check if setting exists
        const existing = await db('app_settings')
          .where('setting_key', key)
          .first();
        
        if (existing) {
          await db('app_settings')
            .where('setting_key', key)
            .update({
              setting_value: JSON.stringify(value),
              updated_at: new Date()
            });
        } else {
          await db('app_settings').insert({
            setting_key: key,
            setting_value: JSON.stringify(value),
            setting_type: 'database_backup'
          });
        }
        
        updates.push(key);
      }
    }
    
    // Restart scheduled backups if enabled state changed
    if (updates.includes('database_backup_enabled') || updates.includes('database_backup_schedule')) {
      const { startScheduledBackups, stopScheduledBackups } = require('../services/databaseBackup');
      stopScheduledBackups();
      await startScheduledBackups();
    }
    
    res.json({ 
      success: true, 
      updatedSettings: updates,
      message: 'Database backup configuration updated successfully'
    });
  } catch (error) {
    logger.error('Failed to update database backup config:', error);
    res.status(500).json({ error: 'Failed to update configuration' });
  }
});

/**
 * Trigger manual database backup
 */
router.post('/backup', async (req, res) => {
  try {
    if (databaseBackupService.isRunning) {
      return res.status(409).json({ error: 'Backup already in progress' });
    }
    
    // Start backup asynchronously
    res.json({ 
      success: true, 
      message: 'Database backup started',
      trackingUrl: '/api/admin/database-backup/progress'
    });
    
    // Run backup in background
    databaseBackupService.backup(req.body).catch(error => {
      logger.error('Manual database backup failed:', error);
    });
  } catch (error) {
    logger.error('Failed to start database backup:', error);
    res.status(500).json({ error: 'Failed to start backup' });
  }
});

/**
 * Get current backup progress
 */
router.get('/progress', async (req, res) => {
  try {
    const progress = databaseBackupService.getProgress();
    
    res.json({
      isRunning: databaseBackupService.isRunning,
      progress
    });
  } catch (error) {
    logger.error('Failed to get backup progress:', error);
    res.status(500).json({ error: 'Failed to get progress' });
  }
});

/**
 * Get backup history with pagination
 */
router.get('/history', async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 20;
    const offset = (page - 1) * limit;
    
    const [backups, totalCount] = await Promise.all([
      db('database_backup_runs')
        .orderBy('started_at', 'desc')
        .limit(limit)
        .offset(offset),
      db('database_backup_runs').count('* as count').first()
    ]);
    
    res.json({
      backups,
      pagination: {
        page,
        limit,
        total: totalCount.count,
        pages: Math.ceil(totalCount.count / limit)
      }
    });
  } catch (error) {
    logger.error('Failed to get backup history:', error);
    res.status(500).json({ error: 'Failed to get history' });
  }
});

/**
 * Delete old backup files
 */
router.delete('/cleanup', async (req, res) => {
  try {
    const { retentionDays = 30 } = req.body;
    
    await databaseBackupService.cleanupOldBackups(retentionDays);
    
    res.json({ 
      success: true, 
      message: `Cleaned up backups older than ${retentionDays} days`
    });
  } catch (error) {
    logger.error('Failed to cleanup old backups:', error);
    res.status(500).json({ error: 'Failed to cleanup backups' });
  }
});

/**
 * Test database backup configuration
 */
router.post('/test', async (req, res) => {
  try {
    const config = await databaseBackupService.getBackupConfig();
    
    // Test database connection
    const testResults = {
      databaseConnection: false,
      destinationWritable: false,
      compressionAvailable: true,
      estimatedSize: null
    };
    
    // Test database connection
    try {
      await db.raw('SELECT 1');
      testResults.databaseConnection = true;
    } catch (error) {
      testResults.databaseConnectionError = error.message;
    }
    
    // Test destination path
    if (config.destinationPath) {
      try {
        const fs = require('fs').promises;
        const testFile = `${config.destinationPath}/.test-${Date.now()}`;
        await fs.writeFile(testFile, 'test');
        await fs.unlink(testFile);
        testResults.destinationWritable = true;
      } catch (error) {
        testResults.destinationError = error.message;
      }
    }
    
    // Estimate database size
    try {
      testResults.estimatedSize = await databaseBackupService.getDatabaseSize();
    } catch (error) {
      testResults.sizeError = error.message;
    }
    
    res.json({
      success: testResults.databaseConnection && testResults.destinationWritable,
      results: testResults
    });
  } catch (error) {
    logger.error('Failed to test backup configuration:', error);
    res.status(500).json({ error: 'Failed to test configuration' });
  }
});

/**
 * Get table checksums
 */
router.get('/checksums', async (req, res) => {
  try {
    const checksums = await databaseBackupService.getTableChecksums();
    
    res.json({
      checksums,
      tableCount: Object.keys(checksums).length,
      totalRows: Object.values(checksums).reduce((sum, table) => sum + table.rowCount, 0)
    });
  } catch (error) {
    logger.error('Failed to get table checksums:', error);
    res.status(500).json({ error: 'Failed to get checksums' });
  }
});

module.exports = router;