<?php
// /upload_backup_chunk.php
// Script para recibir chunks de backups .sql y restaurarlos.

session_start();
header('Content-Type: application/json');

// 1. Verificar permisos (solo Superadmin)
if (!isset($_SESSION['user_id']) || !isset($_SESSION['user_rol']) || $_SESSION['user_rol'] !== 'superadmin') {
    http_response_code(403);
    echo json_encode(['status' => 'error', 'message' => 'Acceso denegado.']);
    exit;
}

// 2. Definir directorio de backups
$backupDir = __DIR__ . '/_backups';

// 3. Validar que el directorio exista y se pueda escribir
if (!is_dir($backupDir)) {
    @mkdir($backupDir, 0775, true);
    @file_put_contents($backupDir . '/.htaccess', "Deny from all");
}
if (!is_writable($backupDir)) {
    http_response_code(500);
    echo json_encode(['status' => 'error', 'message' => 'Error: El directorio de backups no tiene permisos de escritura.']);
    exit;
}

try {
    // 4. Obtener y validar parámetros
    $chunkIndex = (int)($_POST['chunkIndex'] ?? -1);
    $totalChunks = (int)($_POST['totalChunks'] ?? -1);

    // Usar basename() para evitar directory traversal
    $originalFilename = basename($_POST['originalFilename'] ?? '');
    $tempFilename = basename($_POST['tempFilename'] ?? ''); // Ej: 1678886541_backup.sql.part

    if ($chunkIndex < 0 || $totalChunks <= 0 || empty($originalFilename) || empty($tempFilename)) {
        throw new Exception('Parámetros de subida inválidos.');
    }

    // Validar extensiones por seguridad
    if (!str_ends_with($originalFilename, '.sql')) {
        throw new Exception('Tipo de archivo inválido. Solo se permite .sql.');
    }
    if (!str_ends_with($tempFilename, '.sql.part')) {
        throw new Exception('Nombre de archivo temporal inválido.');
    }

    // 5. Validar el chunk subido
    if (!isset($_FILES['backupFileChunk']) || $_FILES['backupFileChunk']['error'] !== UPLOAD_ERR_OK) {
        throw new Exception('Error en la subida del chunk: ' . ($_FILES['backupFileChunk']['error'] ?? 'desconocido'));
    }

    $chunkTmpPath = $_FILES['backupFileChunk']['tmp_name'];
    $tempFilePath = $backupDir . '/' . $tempFilename;

    // 6. Mover y ensamblar el chunk
    // file_put_contents con FILE_APPEND es atómico y más seguro para esto
    $chunkContent = file_get_contents($chunkTmpPath);
    if (file_put_contents($tempFilePath, $chunkContent, FILE_APPEND | LOCK_EX) === false) {
        throw new Exception('No se pudo escribir el chunk en el archivo temporal.');
    }
    @unlink($chunkTmpPath); // Limpiar el chunk temporal de PHP

    // 7. Comprobar si es el último chunk
    if (($chunkIndex + 1) == $totalChunks) {
        // --- ES EL ÚLTIMO CHUNK: Ensamblar y Restaurar ---

        // 7.1. Renombrar el archivo .part a .sql
        $finalFilename = str_replace('.sql.part', '.sql', $tempFilename);
        $finalFilePath = $backupDir . '/' . $finalFilename;

        if (!rename($tempFilePath, $finalFilePath)) {
            throw new Exception('No se pudo renombrar el archivo temporal completado.');
        }

        // 7.2. Cargar dependencias para la restauración
        // Asegúrate de que la ruta a db.php es correcta
        require_once __DIR__ . '/db.php';
        require_once __DIR__ . '/backup_utils.php';

        if (!function_exists('restoreDatabaseFromSQL')) {
             @unlink($finalFilePath); // Limpiar si falta la función
             throw new Exception('Error crítico: La función restoreDatabaseFromSQL no está disponible.');
        }

        // 7.3. Obtener configuración de DB (definida en db.php)
        $db_config = [
            'host' => DB_HOST,
            'user' => DB_USER,
            'pass' => DB_PASS,
            'name' => DB_NAME
        ];

        // 7.4. Ejecutar la restauración
        $result = restoreDatabaseFromSQL($db_config, $finalFilePath);

        // (Opcional) Limpiar el archivo .sql subido después de la restauración
        // if ($result['status'] === 'success') {
        //     @unlink($finalFilePath);
        // }

        // 7.5. Devolver el resultado final de la restauración
        echo json_encode($result);

    } else {
        // --- No es el último chunk: Enviar confirmación ---
        echo json_encode(['status' => 'chunk_success', 'message' => "Chunk $chunkIndex/$totalChunks recibido."]);
    }

} catch (Exception $e) {
    http_response_code(500);
    echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
    // Intentar limpiar archivos temporales en caso de error
    if (isset($tempFilePath) && file_exists($tempFilePath)) {
        @unlink($tempFilePath);
    }
    if (isset($chunkTmpPath) && file_exists($chunkTmpPath)) {
        @unlink($chunkTmpPath);
    }
}
exit;
?>
