<?php
// Don't set content type for download action
if (($_REQUEST['action'] ?? '') !== 'download') {
    header('Content-Type: application/json');
}

// Check API permission
check_api_permission('backup-actions');

require_once '../libs/BackupTarget.php';
require_once '../libs/BackupHistory.php';
require_once '../libs/BackupEngine.php';
require_once '../libs/BackupStorage.php';
require_once '../libs/BackupSchedule.php';

use WHPBackup\BackupTarget;
use WHPBackup\BackupHistory;
use WHPBackup\BackupEngine;
use WHPBackup\BackupStorage;
use WHPBackup\BackupSchedule;

// Verify nonce - Note: auto-prepend already validates the session/nonce
// We just need to check that the user is authenticated
if (!defined('AUTH_USER')) {
    http_response_code(403);
    echo json_encode(['success' => false, 'message' => 'Authentication required']);
    exit;
}

$action = $_REQUEST['action'] ?? '';
$username = AUTH_USER;
$isRoot = $username === 'root';

try {
    switch ($action) {
        case 'create_target':
            // Convert checkbox value to boolean
            $_POST['is_global'] = isset($_POST['is_global']) && $_POST['is_global'] === 'on' ? 1 : 0;
            
            if (!$isRoot && $_POST['is_global']) {
                // Non-root users cannot create global targets
                throw new Exception('Permission denied: Only root can create global targets');
            }
            
            // Set owner based on global flag
            $_POST['owner'] = $_POST['is_global'] ? null : $username;
            
            $target = new BackupTarget();
            $result = $target->create($_POST);
            
            if ($result) {
                echo json_encode(['success' => true, 'message' => 'Target created successfully']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to create target']);
            }
            break;
            
        case 'get_target':
            $targetId = $_GET['target_id'] ?? '';
            if (!$targetId) {
                throw new Exception('Target ID required');
            }
            
            $target = new BackupTarget(null, $targetId);
            if (!$target->canManage($username)) {
                throw new Exception('Permission denied');
            }
            
            $targetData = $target->getDataForEdit();
            echo json_encode(['success' => true, 'target' => $targetData]);
            break;
            
        case 'update_target':
            $targetId = $_POST['targetId'] ?? '';
            if (!$targetId) {
                throw new Exception('Target ID required');
            }
            
            // Convert checkbox value to boolean
            if (isset($_POST['is_global'])) {
                $_POST['is_global'] = $_POST['is_global'] === 'on' ? 1 : 0;
            }
            
            $target = new BackupTarget(null, $targetId);
            if (!$target->canManage($username)) {
                throw new Exception('Permission denied');
            }
            
            $result = $target->update($_POST);
            
            if ($result) {
                echo json_encode(['success' => true, 'message' => 'Target updated successfully']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to update target']);
            }
            break;
            
        case 'delete_target':
            $targetId = $_POST['target_id'] ?? '';
            if (!$targetId) {
                throw new Exception('Target ID required');
            }
            
            $target = new BackupTarget(null, $targetId);
            if (!$target->canManage($username)) {
                throw new Exception('Permission denied');
            }
            
            $result = $target->delete();
            
            if ($result) {
                echo json_encode(['success' => true, 'message' => 'Target deleted successfully']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to delete target']);
            }
            break;
            
        case 'test_target':
            $targetId = $_POST['target_id'] ?? '';
            if (!$targetId) {
                throw new Exception('Target ID required');
            }
            
            $target = new BackupTarget(null, $targetId);
            if (!$target->canAccess($username)) {
                throw new Exception('Permission denied');
            }
            
            $storage = new BackupStorage($target->getCredentials());
            $result = $storage->testConnection();
            
            if ($result['success']) {
                echo json_encode(['success' => true, 'message' => 'Connection successful']);
            } else {
                echo json_encode(['success' => false, 'message' => $result['error']]);
            }
            break;
            
        case 'create_backup':
            $backupType = $_POST['backup_type'] ?? '';
            $targetId = $_POST['target_id'] ?? '';
            
            if (!$backupType || !$targetId) {
                throw new Exception('Backup type and target ID required');
            }
            
            // Allow root to backup for other users
            $backupUser = $username;
            if ($isRoot && isset($_POST['backup_user']) && !empty($_POST['backup_user'])) {
                $backupUser = $_POST['backup_user'];
            }
            
            $engine = new BackupEngine();
            
            switch ($backupType) {
                case 'site':
                    $site = $_POST['site'] ?? '';
                    if (!$site) {
                        throw new Exception('Site selection required');
                    }
                    
                    if ($site === '*') {
                        // Backup all sites
                        $sites = $engine->getUserSites($backupUser);
                        if (empty($sites)) {
                            throw new Exception('No sites found for user');
                        }
                        
                        $results = [];
                        foreach ($sites as $singleSite) {
                            try {
                                $results[] = $engine->createSiteBackup($backupUser, $singleSite, $targetId);
                            } catch (Exception $e) {
                                // Log error but continue with other sites
                                error_log("Failed to backup site $singleSite: " . $e->getMessage());
                            }
                        }
                        
                        if (empty($results)) {
                            throw new Exception('Failed to backup any sites');
                        }
                        
                        $result = [
                            'success' => true,
                            'backup_id' => $results[0]['backup_id'], // Return first backup ID
                            'message' => 'Created ' . count($results) . ' site backups'
                        ];
                    } else {
                        // Check if site is in format "user/domain" (from root user selection)
                        if (strpos($site, '/') !== false) {
                            list($siteUser, $siteDomain) = explode('/', $site, 2);
                            // Verify the extracted user matches the backup user or use the extracted user if root
                            if ($isRoot) {
                                $backupUser = $siteUser;
                            } elseif ($siteUser !== $backupUser) {
                                throw new Exception('Access denied to site from different user');
                            }
                            $site = $siteDomain;
                        }
                        $result = $engine->createSiteBackup($backupUser, $site, $targetId);
                    }
                    break;
                    
                case 'userfiles':
                    $result = $engine->createUserfilesBackup($backupUser, $targetId);
                    break;
                    
                case 'database':
                    $database = $_POST['database'] ?? '';
                    if (!$database) {
                        throw new Exception('Database selection required');
                    }
                    
                    if ($database === '*') {
                        // Backup all databases
                        $databases = $engine->getUserDatabases($backupUser);
                        if (empty($databases)) {
                            throw new Exception('No databases found for user');
                        }
                        
                        // Log the databases found for debugging
                        error_log("Bulk database backup for user $backupUser - Found databases: " . implode(', ', $databases));
                        
                        $results = [];
                        foreach ($databases as $singleDb) {
                            try {
                                error_log("Processing database backup: $singleDb");
                                $results[] = $engine->createDatabaseBackup($backupUser, $singleDb, $targetId);
                            } catch (Exception $e) {
                                // Log error but continue with other databases
                                error_log("Failed to backup database $singleDb: " . $e->getMessage());
                            }
                        }
                        
                        if (empty($results)) {
                            throw new Exception('Failed to backup any databases');
                        }
                        
                        $result = [
                            'success' => true,
                            'backup_id' => $results[0]['backup_id'], // Return first backup ID
                            'message' => 'Created ' . count($results) . ' database backups'
                        ];
                    } else {
                        $result = $engine->createDatabaseBackup($backupUser, $database, $targetId);
                    }
                    break;
                    
                default:
                    throw new Exception('Invalid backup type');
            }
            
            if ($result['success']) {
                echo json_encode([
                    'success' => true, 
                    'message' => 'Backup created successfully',
                    'backup_id' => $result['backup_id']
                ]);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to create backup']);
            }
            break;
            
        case 'retry_backup':
            $backupId = $_POST['backup_id'] ?? '';
            if (!$backupId) {
                throw new Exception('Backup ID required');
            }

            $engine = new BackupEngine();
            $result = $engine->retryBackup($backupId, $username);

            echo json_encode($result);
            break;

        case 'delete_backup':
            $backupId = $_POST['backup_id'] ?? '';
            if (!$backupId) {
                throw new Exception('Backup ID required');
            }
            
            $engine = new BackupEngine();
            $result = $engine->deleteBackup($backupId, $username);
            
            if ($result) {
                echo json_encode(['success' => true, 'message' => 'Backup deleted successfully']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to delete backup']);
            }
            break;
            
        case 'delete_backups':
            $backupIds = $_POST['backup_ids'] ?? '';
            if (!$backupIds) {
                throw new Exception('Backup IDs required');
            }
            
            // Parse comma-separated IDs
            $ids = explode(',', $backupIds);
            $ids = array_map('trim', $ids);
            $ids = array_filter($ids); // Remove empty values
            
            if (empty($ids)) {
                throw new Exception('No valid backup IDs provided');
            }
            
            $engine = new BackupEngine();
            $successCount = 0;
            $failCount = 0;
            $errors = [];
            
            foreach ($ids as $backupId) {
                try {
                    $result = $engine->deleteBackup($backupId, $username);
                    if ($result) {
                        $successCount++;
                    } else {
                        $failCount++;
                        $errors[] = "Failed to delete backup ID: $backupId";
                    }
                } catch (Exception $e) {
                    $failCount++;
                    $errors[] = "Error deleting backup ID $backupId: " . $e->getMessage();
                }
            }
            
            if ($failCount === 0) {
                echo json_encode([
                    'success' => true, 
                    'message' => "$successCount backup(s) deleted successfully"
                ]);
            } else if ($successCount === 0) {
                echo json_encode([
                    'success' => false, 
                    'message' => "Failed to delete all backups: " . implode(', ', $errors)
                ]);
            } else {
                echo json_encode([
                    'success' => true, 
                    'message' => "$successCount backup(s) deleted successfully, $failCount failed",
                    'errors' => $errors
                ]);
            }
            break;
            
        case 'download':
            $backupId = $_GET['backup_id'] ?? '';
            if (!$backupId) {
                throw new Exception('Backup ID required');
            }
            
            // Ensure no output before download
            ob_clean();
            
            $engine = new BackupEngine();
            $engine->downloadBackup($backupId, $username);
            exit; // Don't output JSON for downloads
            
        case 'list_backups':
            $filters = [
                'exclude_deleted' => true,
                'limit' => $_GET['limit'] ?? 50,
                'offset' => $_GET['offset'] ?? 0
            ];
            
            if (!$isRoot) {
                $filters['user'] = $username;
            } elseif (isset($_GET['user'])) {
                $filters['user'] = $_GET['user'];
            }
            
            if (isset($_GET['target_id'])) {
                $filters['target_id'] = $_GET['target_id'];
            }
            
            if (isset($_GET['backup_type'])) {
                $filters['backup_type'] = $_GET['backup_type'];
            }
            
            if (isset($_GET['status'])) {
                $filters['status'] = $_GET['status'];
            }
            
            if (isset($_GET['search'])) {
                $filters['search'] = $_GET['search'];
            }
            
            $backups = BackupHistory::listBackups(null, $filters);
            $totalCount = BackupHistory::countBackups(null, $filters);
            
            echo json_encode([
                'success' => true,
                'backups' => $backups,
                'total' => $totalCount
            ]);
            break;
            
        case 'get_backup':
            $backupId = $_GET['backup_id'] ?? '';
            if (!$backupId) {
                throw new Exception('Backup ID required');
            }
            
            $history = new BackupHistory(null, $backupId);
            if (!$history->canAccess($username)) {
                throw new Exception('Permission denied');
            }
            
            echo json_encode([
                'success' => true,
                'backup' => $history->getData()
            ]);
            break;
            
        case 'get_targets':
            $targets = BackupTarget::listTargets(null, $username);
            echo json_encode([
                'success' => true,
                'targets' => $targets
            ]);
            break;
            
        case 'get_target':
            $targetId = $_GET['target_id'] ?? '';
            if (!$targetId) {
                throw new Exception('Target ID required');
            }
            
            $target = new BackupTarget(null, $targetId);
            if (!$target->canAccess($username)) {
                throw new Exception('Permission denied');
            }
            
            echo json_encode([
                'success' => true,
                'target' => $target->getData()
            ]);
            break;
            
        case 'cleanup_old_backups':
            if (!$isRoot) {
                throw new Exception('Permission denied');
            }
            
            $targetId = $_POST['target_id'] ?? null;
            $engine = new BackupEngine();
            $engine->cleanupOldBackups($targetId);
            
            echo json_encode(['success' => true, 'message' => 'Cleanup completed']);
            break;
            
        case 'get_user_resources':
            $engine = new BackupEngine();
            $sites = $engine->getUserSites($username);
            $databases = $engine->getUserDatabases($username);
            
            echo json_encode([
                'success' => true,
                'sites' => $sites,
                'databases' => $databases
            ]);
            break;
            
        case 'get_backup_stats':
            $filters = $isRoot ? [] : ['user' => $username];
            
            $totalBackups = BackupHistory::countBackups(null, $filters);
            $totalSize = BackupHistory::getTotalSize(null, $filters);
            
            $completedFilters = array_merge($filters, ['status' => 'completed']);
            $completedBackups = BackupHistory::countBackups(null, $completedFilters);
            
            $runningFilters = array_merge($filters, ['status' => 'running']);
            $runningBackups = BackupHistory::countBackups(null, $runningFilters);
            
            echo json_encode([
                'success' => true,
                'stats' => [
                    'total_backups' => $totalBackups,
                    'completed_backups' => $completedBackups,
                    'running_backups' => $runningBackups,
                    'total_size' => $totalSize
                ]
            ]);
            break;
            
        case 'create_schedule':
            if (!isset($_POST['target_id']) || !isset($_POST['backup_type']) || !isset($_POST['schedule_type'])) {
                throw new Exception('Missing required fields');
            }
            
            $scheduleData = [
                'user' => $isRoot && isset($_POST['schedule_user']) ? $_POST['schedule_user'] : $username,
                'target_id' => $_POST['target_id'],
                'backup_type' => $_POST['backup_type'],
                'resource_name' => empty($_POST['resource_name']) ? null : $_POST['resource_name'],
                'schedule_type' => $_POST['schedule_type'],
                'schedule_time' => $_POST['schedule_time'] ?? '02:00:00',
                'schedule_day' => empty($_POST['schedule_day']) ? null : intval($_POST['schedule_day']),
                'max_retention' => $_POST['max_retention'] ?? 30,
                'is_active' => isset($_POST['is_active']) ? 1 : 0
            ];
            
            // Validate target access
            $target = new BackupTarget(null, $scheduleData['target_id']);
            if (!$target->canAccess($scheduleData['user'])) {
                throw new Exception('Access denied to backup target');
            }
            
            $schedule = new BackupSchedule();
            $result = $schedule->create($scheduleData);
            
            if ($result) {
                echo json_encode(['success' => true, 'message' => 'Schedule created successfully']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to create schedule']);
            }
            break;
            
        case 'update_schedule':
            $scheduleId = $_POST['schedule_id'] ?? '';
            if (!$scheduleId) {
                throw new Exception('Schedule ID required');
            }
            
            $schedule = new BackupSchedule(null, $scheduleId);
            if (!$schedule->canManage($username)) {
                throw new Exception('Permission denied');
            }
            
            // Process checkbox value
            $updateData = $_POST;
            if (isset($updateData['is_active'])) {
                // Convert checkbox value to integer (0 or 1)
                $updateData['is_active'] = ($updateData['is_active'] === 'on' || $updateData['is_active'] === '1') ? 1 : 0;
            }
            
            $result = $schedule->update($updateData);
            
            if ($result) {
                echo json_encode(['success' => true, 'message' => 'Schedule updated successfully']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to update schedule']);
            }
            break;
            
        case 'delete_schedule':
            $scheduleId = $_POST['schedule_id'] ?? '';
            if (!$scheduleId) {
                throw new Exception('Schedule ID required');
            }
            
            $schedule = new BackupSchedule(null, $scheduleId);
            if (!$schedule->canManage($username)) {
                throw new Exception('Permission denied');
            }
            
            $result = $schedule->delete();
            
            if ($result) {
                echo json_encode(['success' => true, 'message' => 'Schedule deleted successfully']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to delete schedule']);
            }
            break;
            
        case 'get_schedules':
            $filters = [
                'limit' => $_GET['limit'] ?? 50,
                'offset' => $_GET['offset'] ?? 0
            ];
            
            if (!$isRoot) {
                $filters['user'] = $username;
            } elseif (isset($_GET['user'])) {
                $filters['user'] = $_GET['user'];
            }
            
            if (isset($_GET['target_id'])) {
                $filters['target_id'] = $_GET['target_id'];
            }
            
            if (isset($_GET['backup_type'])) {
                $filters['backup_type'] = $_GET['backup_type'];
            }
            
            $schedules = BackupSchedule::listSchedules(null, $filters);
            
            echo json_encode([
                'success' => true,
                'schedules' => $schedules
            ]);
            break;
            
        case 'get_schedule':
            $scheduleId = $_GET['schedule_id'] ?? '';
            if (!$scheduleId) {
                throw new Exception('Schedule ID required');
            }
            
            $schedule = new BackupSchedule(null, $scheduleId);
            if (!$schedule->canManage($username)) {
                throw new Exception('Permission denied');
            }
            
            echo json_encode([
                'success' => true,
                'schedule' => $schedule->getData()
            ]);
            break;
            
        case 'test_schedule':
            $scheduleId = $_POST['schedule_id'] ?? '';
            if (!$scheduleId) {
                throw new Exception('Schedule ID required');
            }
            
            $schedule = new BackupSchedule(null, $scheduleId);
            if (!$schedule->canManage($username)) {
                throw new Exception('Permission denied');
            }
            
            $scheduleData = $schedule->getData();
            $engine = new BackupEngine();
            
            // Create a test backup based on the schedule
            switch ($scheduleData['backup_type']) {
                case 'site':
                    if ($scheduleData['resource_name']) {
                        $result = $engine->createSiteBackup($scheduleData['user'], $scheduleData['resource_name'], $scheduleData['target_id']);
                    } else {
                        // Get first site for testing
                        $sites = $engine->getUserSites($scheduleData['user']);
                        if (empty($sites)) {
                            throw new Exception('No sites found for user: ' . $scheduleData['user']);
                        }
                        $result = $engine->createSiteBackup($scheduleData['user'], $sites[0], $scheduleData['target_id']);
                    }
                    break;
                    
                case 'userfiles':
                    $result = $engine->createUserfilesBackup($scheduleData['user'], $scheduleData['target_id']);
                    break;
                    
                case 'database':
                    if ($scheduleData['resource_name']) {
                        $result = $engine->createDatabaseBackup($scheduleData['user'], $scheduleData['resource_name'], $scheduleData['target_id']);
                    } else {
                        // Get first database for testing
                        $databases = $engine->getUserDatabases($scheduleData['user']);
                        if (empty($databases)) {
                            throw new Exception('No databases found for user: ' . $scheduleData['user']);
                        }
                        $result = $engine->createDatabaseBackup($scheduleData['user'], $databases[0], $scheduleData['target_id']);
                    }
                    break;
                    
                default:
                    throw new Exception('Invalid backup type');
            }
            
            if ($result['success']) {
                echo json_encode([
                    'success' => true,
                    'message' => 'Test backup started successfully',
                    'backup_id' => $result['backup_id']
                ]);
            } else {
                echo json_encode([
                    'success' => false,
                    'message' => 'Failed to start test backup'
                ]);
            }
            break;
            
        case 'run_scheduler':
            if (!$isRoot) {
                throw new Exception('Permission denied - only root can run scheduler');
            }
            
            // Run the scheduler script
            $scriptPath = '/root/whp/scripts/backup-scheduler.php';
            if (!file_exists($scriptPath)) {
                throw new Exception('Scheduler script not found');
            }
            
            // Run scheduler in background
            $command = "php " . escapeshellarg($scriptPath) . " > /dev/null 2>&1 &";
            exec($command, $output, $returnCode);
            
            echo json_encode([
                'success' => true,
                'message' => 'Scheduler started successfully'
            ]);
            break;
            
        default:
            throw new Exception('Invalid action');
    }
    
} catch (Exception $e) {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'message' => $e->getMessage()
    ]);
}