<?php
/**
 * POS EXPRESS - ELITE DASHBOARD v6.0
 * Concepto: Segregación de Responsabilidades (SoR)
 * UI: Bootstrap 5 + SweetAlert2 + Layout Modular
 */
ob_start();
session_start();

// ==========================================
// 1. CONFIGURACIÓN DEL SISTEMA
// ==========================================
$config = [
    'app_password' => '33COMrXx', // <--- CONTRASEÑA DE ACCESO
    'db_host'      => 'localhost',
    'db_user'      => 'root',
    'db_pass'      => '33comRxXMysql', 
    'root_path'    => $_SERVER['DOCUMENT_ROOT'], // O cambia a __DIR__ si prefieres restringir
    'backup_dir'   => 'respaldos_sistema' 
];

// ==========================================
// 2. LÓGICA DE BACKEND (API)
// ==========================================
$localScriptPath = realpath(__DIR__); 
$backupRepo = $localScriptPath . DIRECTORY_SEPARATOR . $config['backup_dir'];
if (!file_exists($backupRepo)) { mkdir($backupRepo, 0755, true); }

// --- LOGOUT ---
if (isset($_GET['logout'])) {
    session_destroy();
    echo "<script>window.location.href='?';</script>"; exit;
}

// --- LOGIN ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login_pass'])) {
    if ($_POST['login_pass'] === $config['app_password']) {
        $_SESSION['Acceso_Elite_v6'] = true;
        echo "<script>window.location.href='" . strtok($_SERVER["REQUEST_URI"], '?') . "';</script>"; exit;
    } else {
        $login_error = "Credenciales inválidas.";
    }
}

// --- BLOQUEO DE SEGURIDAD ---
if (!isset($_SESSION['Acceso_Elite_v6']) || $_SESSION['Acceso_Elite_v6'] !== true) {
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login - Elite Dashboard</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body { background: #f3f4f6; display: flex; align-items: center; justify-content: center; height: 100vh; font-family: system-ui, -apple-system, sans-serif; }
        .card-login { background: white; padding: 2.5rem; border-radius: 1rem; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); width: 100%; max-width: 400px; }
        .btn-auth { background: #2563eb; color: white; width: 100%; padding: 0.75rem; border-radius: 0.5rem; border: none; font-weight: 600; margin-top: 1rem; }
        .btn-auth:hover { background: #1d4ed8; }
    </style>
</head>
<body>
    <div class="card-login text-center">
        <h4 class="fw-bold text-dark mb-4">🔐 SECURITY ACCESS</h4>
        <?php if(isset($login_error)) echo "<div class='alert alert-danger p-2 small'>$login_error</div>"; ?>
        <form method="POST">
            <input type="password" name="login_pass" class="form-control bg-light border-0 py-3" placeholder="Ingresa tu contraseña..." required autofocus>
            <button class="btn-auth">INICIAR SESIÓN</button>
        </form>
    </div>
</body>
</html>
<?php exit; }

// --- DESCARGAR ARCHIVO ---
if (isset($_GET['action']) && $_GET['action'] === 'download' && isset($_GET['file'])) {
    $file = basename($_GET['file']);
    $filePath = $backupRepo . DIRECTORY_SEPARATOR . $file;
    if (file_exists($filePath)) {
        if (ob_get_level()) ob_end_clean();
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="'.$file.'"');
        header('Content-Length: ' . filesize($filePath));
        readfile($filePath); exit;
    }
}
// --- BORRAR ARCHIVO ---
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['file'])) {
    $file = basename($_GET['file']);
    @unlink($backupRepo . DIRECTORY_SEPARATOR . $file);
    header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); exit;
}

// --- PROCESADOR AJAX DE RESPALDOS ---
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action']) && $_POST['action'] == 'backup') {
    if (ob_get_level()) ob_end_clean();
    header('Content-Type: application/json');
    set_time_limit(0); ini_set('memory_limit', '2048M');

    $type = $_POST['type'] ?? 'mixed'; // 'files' o 'db'
    $items = $_POST['items'] ?? [];
    $dbs = $_POST['dbs'] ?? [];
    
    // Nombramiento Inteligente
    $prefix = ($type === 'files') ? 'FILES_' : (($type === 'db') ? 'SQL_' : 'FULL_');
    $zipName = $prefix . date('Ymd_His') . '.zip';
    $zipPath = $backupRepo . DIRECTORY_SEPARATOR . $zipName;

    $zip = new ZipArchive();
    if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
        echo json_encode(["status"=>"error", "msg"=>"Error de permisos al crear ZIP."]); exit;
    }

    $tempFiles = [];

    // 1. PROCESAR BASES DE DATOS
    if (!empty($dbs)) {
        foreach ($dbs as $db) {
            $sqlFile = $db . ".sql";
            $sqlPath = $backupRepo . DIRECTORY_SEPARATOR . $sqlFile;
            $cmd = sprintf("mysqldump --opt --hex-blob -h %s -u %s -p'%s' %s > %s",
                escapeshellarg($config['db_host']), escapeshellarg($config['db_user']), $config['db_pass'], escapeshellarg($db), escapeshellarg($sqlPath));
            exec($cmd);
            if (file_exists($sqlPath) && filesize($sqlPath) > 0) {
                $zip->addFile($sqlPath, "BASEDATOS/{$sqlFile}");
                $tempFiles[] = $sqlPath;
            }
        }
    }

    // 2. PROCESAR ARCHIVOS
    if (!empty($items)) {
        foreach ($items as $relItem) {
            $realPath = realpath($config['root_path'] . DIRECTORY_SEPARATOR . $relItem);
            if (!$realPath || !file_exists($realPath) || strpos($realPath, $backupRepo) === 0) continue;

            if (is_dir($realPath)) {
                $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($realPath, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::LEAVES_ONLY);
                foreach ($files as $name => $file) {
                    if (!$file->isDir()) {
                        $filePath = $file->getRealPath();
                        $zipPathInside = "ARCHIVOS/" . $relItem . "/" . substr($filePath, strlen($realPath) + 1);
                        $zip->addFile($filePath, $zipPathInside);
                    }
                }
            } else {
                $zip->addFile($realPath, "ARCHIVOS/" . basename($realPath));
            }
        }
    }

    $zip->close();
    foreach ($tempFiles as $t) @unlink($t);
    echo json_encode(["status"=>"success", "file"=>$zipName]); exit;
}

// ==========================================
// 3. DATOS DE NAVEGACIÓN
// ==========================================

// BDs
$availableDbs = [];
$dbError = null;
try {
    $pdo = new PDO("mysql:host={$config['db_host']}", $config['db_user'], $config['db_pass']);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $stmt = $pdo->query("SHOW DATABASES WHERE `Database` NOT IN ('information_schema', 'performance_schema', 'mysql', 'sys')");
    $availableDbs = $stmt->fetchAll(PDO::FETCH_COLUMN);
} catch (Exception $e) { $dbError = "Error MySQL: " . $e->getMessage(); }

// Archivos
$currentRelPath = str_replace(['..', './'], '', $_GET['path'] ?? '');
$fullPath = realpath($config['root_path'] . DIRECTORY_SEPARATOR . $currentRelPath);
if (!$fullPath || strpos($fullPath, $config['root_path']) !== 0) {
    $fullPath = $config['root_path'];
    $currentRelPath = '';
}
$dirContent = array_diff(scandir($fullPath), ['.', '..']);
$backups = array_diff(scandir($backupRepo), ['.', '..']);
arsort($backups);
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Elite Dashboard v6.0</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
    
    <style>
        :root { 
            --primary: #0f172a; 
            --accent-file: #0284c7; /* Azul Claro */
            --accent-db: #7c3aed;   /* Violeta */
            --bg-body: #f1f5f9;
        }
        body { background: var(--bg-body); font-family: 'Inter', sans-serif; color: #334155; }
        
        /* Navbar */
        .navbar-custom { background: white; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1); padding: 1rem 2rem; }
        
        /* Cards Layout */
        .card-custom { border: none; border-radius: 12px; background: white; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); height: 100%; overflow: hidden; display: flex; flex-direction: column; }
        .card-header-custom { padding: 1.25rem; font-weight: 700; text-transform: uppercase; font-size: 0.85rem; letter-spacing: 0.05em; display: flex; justify-content: space-between; align-items: center; }
        
        /* Specific Styles */
        .header-files { background: #f0f9ff; color: var(--accent-file); border-bottom: 2px solid var(--accent-file); }
        .header-db { background: #f5f3ff; color: var(--accent-db); border-bottom: 2px solid var(--accent-db); }
        .header-repo { background: #ecfdf5; color: #059669; border-bottom: 2px solid #059669; }

        /* Browsers */
        .scroll-area { flex-grow: 1; overflow-y: auto; height: 450px; padding: 0; }
        .list-item { padding: 10px 15px; border-bottom: 1px solid #f1f5f9; display: flex; align-items: center; transition: 0.15s; font-size: 0.95rem; }
        .list-item:hover { background: #f8fafc; }
        
        /* Buttons */
        .btn-files { background: var(--accent-file); color: white; width: 100%; border: none; padding: 15px; font-weight: 600; transition: 0.2s; border-radius: 0 0 12px 12px; }
        .btn-files:hover { background: #0369a1; color: white; }
        
        .btn-db { background: var(--accent-db); color: white; width: 100%; border: none; padding: 15px; font-weight: 600; transition: 0.2s; border-radius: 0 0 12px 12px; }
        .btn-db:hover { background: #6d28d9; color: white; }

        /* Scrollbar */
        ::-webkit-scrollbar { width: 6px; }
        ::-webkit-scrollbar-track { background: transparent; }
        ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
    </style>
</head>
<body>

<nav class="navbar-custom d-flex justify-content-between align-items-center mb-4">
    <div class="d-flex align-items-center">
        <div class="bg-dark text-white rounded p-2 me-3"><i class="fa-solid fa-layer-group"></i></div>
        <div>
            <h5 class="m-0 fw-bold text-dark">DASHBOARD DE RESPALDO</h5>
            <small class="text-muted">Gestión Separada de Activos</small>
        </div>
    </div>
    <a href="?logout=true" class="btn btn-outline-danger btn-sm fw-bold border-2">CERRAR SESIÓN</a>
</nav>

<div class="container-fluid px-4">
    <div class="row g-4">
        
        <div class="col-lg-5">
            <div class="card-custom">
                <div class="card-header-custom header-files">
                    <span><i class="fa-regular fa-folder-open me-2"></i> Explorador de Archivos</span>
                    <button class="btn btn-sm btn-light text-primary fw-bold" onclick="toggleChecks('.cb-file')">Todo</button>
                </div>
                
                <div class="bg-light px-3 py-2 small border-bottom text-muted text-truncate">
                    <i class="fa-solid fa-location-dot me-1"></i>
                    ROOT / <?= htmlspecialchars(implode(' / ', array_filter(explode('/', $currentRelPath)))) ?>
                </div>

                <div class="scroll-area">
                    <?php if($currentRelPath): ?>
                        <div class="list-item" style="background:#eff6ff; cursor:pointer;" onclick="location.href='?path=<?= urlencode(dirname($currentRelPath) == '.' ? '' : dirname($currentRelPath)) ?>'">
                            <span class="me-3 text-primary"><i class="fa-solid fa-turn-up"></i></span>
                            <strong>Regresar al nivel superior</strong>
                        </div>
                    <?php endif; ?>

                    <?php foreach($dirContent as $item): 
                        $isDir = is_dir($fullPath . DIRECTORY_SEPARATOR . $item);
                        $rel = ($currentRelPath ? $currentRelPath . '/' : '') . $item;
                    ?>
                    <div class="list-item">
                        <input type="checkbox" class="form-check-input cb-file me-3" value="<?= htmlspecialchars($rel) ?>" style="transform: scale(1.1);">
                        <span class="me-3 text-secondary" style="width:20px; text-align:center;">
                            <i class="fa-<?= $isDir ? 'solid fa-folder text-warning' : 'regular fa-file text-muted' ?>"></i>
                        </span>
                        <?php if($isDir): ?>
                            <a href="?path=<?= urlencode($rel) ?>" class="text-dark fw-bold text-decoration-none flex-grow-1"><?= $item ?></a>
                        <?php else: ?>
                            <span class="text-dark flex-grow-1"><?= $item ?></span>
                        <?php endif; ?>
                    </div>
                    <?php endforeach; ?>
                </div>

                <button class="btn-files" onclick="processBackup('files')">
                    <i class="fa-solid fa-file-zipper me-2"></i> GENERAR ZIP DE ARCHIVOS
                </button>
            </div>
        </div>

        <div class="col-lg-3">
            <div class="card-custom">
                <div class="card-header-custom header-db">
                    <span><i class="fa-solid fa-database me-2"></i> Bases de Datos</span>
                    <button class="btn btn-sm btn-light text-primary fw-bold" onclick="toggleChecks('.cb-db')">Todo</button>
                </div>
                
                <div class="scroll-area bg-white">
                    <?php if($dbError): ?>
                        <div class="p-4 text-center text-danger">
                            <i class="fa-solid fa-triangle-exclamation fa-2x mb-2"></i><br>
                            <?= $dbError ?>
                        </div>
                    <?php else: ?>
                        <?php foreach($availableDbs as $db): ?>
                        <div class="list-item">
                            <input type="checkbox" class="form-check-input cb-db me-3" value="<?= $db ?>" style="transform: scale(1.1);">
                            <span class="me-2 text-secondary"><i class="fa-solid fa-server"></i></span>
                            <span class="fw-bold text-dark"><?= $db ?></span>
                        </div>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </div>

                <button class="btn-db" onclick="processBackup('db')">
                    <i class="fa-solid fa-download me-2"></i> RESPALDAR SQLs
                </button>
            </div>
        </div>

        <div class="col-lg-4">
            <div class="card-custom">
                <div class="card-header-custom header-repo">
                    <span><i class="fa-solid fa-clock-rotate-left me-2"></i> Historial Local</span>
                    <span class="badge bg-success bg-opacity-25 text-success"><?= count($backups) ?></span>
                </div>

                <div class="scroll-area" style="height: 520px;"> <?php if(empty($backups)): ?>
                        <div class="h-100 d-flex flex-column align-items-center justify-content-center text-muted opacity-50">
                            <i class="fa-regular fa-folder-open fa-3x mb-3"></i>
                            <p>Sin respaldos recientes</p>
                        </div>
                    <?php else: ?>
                        <div class="list-group list-group-flush">
                        <?php foreach($backups as $b): 
                             $typeIcon = strpos($b, 'SQL') === 0 ? 'fa-database text-primary' : (strpos($b, 'FILES') === 0 ? 'fa-folder-tree text-info' : 'fa-box-archive text-warning');
                             $size = round(filesize($backupRepo.'/'.$b) / 1024 / 1024, 2);
                        ?>
                            <div class="list-group-item d-flex justify-content-between align-items-center p-3">
                                <div class="d-flex align-items-center overflow-hidden">
                                    <div class="me-3 fs-5"><i class="fa-solid <?= $typeIcon ?>"></i></div>
                                    <div class="text-truncate">
                                        <div class="fw-bold text-dark small text-truncate" style="max-width: 180px;" title="<?= $b ?>"><?= $b ?></div>
                                        <div class="text-muted" style="font-size: 0.7rem;"><?= date("d/m/Y H:i", filemtime($backupRepo.'/'.$b)) ?> • <?= $size ?> MB</div>
                                    </div>
                                </div>
                                <div class="d-flex gap-1">
                                    <a href="?action=download&file=<?= urlencode($b) ?>" class="btn btn-outline-success btn-sm"><i class="fa-solid fa-download"></i></a>
                                    <button class="btn btn-outline-danger btn-sm" onclick="confirmDelete('<?= $b ?>')"><i class="fa-solid fa-trash"></i></button>
                                </div>
                            </div>
                        <?php endforeach; ?>
                        </div>
                    <?php endif; ?>
                </div>
            </div>
        </div>

    </div>
</div>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<script>
function toggleChecks(selector) {
    const status = !$(selector).first().prop('checked');
    $(selector).prop('checked', status);
}

function confirmDelete(file) {
    Swal.fire({
        title: '¿Eliminar?',
        text: file,
        icon: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#ef4444',
        cancelButtonColor: '#64748b',
        confirmButtonText: 'Sí, eliminar',
        cancelButtonText: 'Cancelar'
    }).then((r) => {
        if(r.isConfirmed) location.href = '?action=delete&file=' + encodeURIComponent(file);
    });
}

function processBackup(type) {
    let data = { action: 'backup', type: type };
    let hasSelection = false;

    // Recolectar datos según el botón presionado (Separación estricta)
    if (type === 'files') {
        data.items = $('.cb-file:checked').map((_,e)=>e.value).get();
        if (data.items.length > 0) hasSelection = true;
    } else if (type === 'db') {
        data.dbs = $('.cb-db:checked').map((_,e)=>e.value).get();
        if (data.dbs.length > 0) hasSelection = true;
    }

    if (!hasSelection) {
        return Swal.fire('Nada seleccionado', 'Por favor selecciona al menos un elemento de la lista.', 'info');
    }

    // UI Loading
    Swal.fire({
        title: 'Procesando...',
        html: 'Generando archivo comprimido.<br>Por favor no cierres esta ventana.',
        allowOutsideClick: false,
        didOpen: () => { Swal.showLoading() }
    });

    $.post(window.location.href, data, function(res) {
        if (res.status === 'success') {
            Swal.fire({
                icon: 'success',
                title: '¡Respaldo Listo!',
                text: 'Archivo generado: ' + res.file,
                confirmButtonText: 'Recargar Panel'
            }).then(() => location.reload());
        } else {
            Swal.fire('Error', res.msg, 'error');
        }
    }, 'json').fail(function() {
        Swal.fire('Error de Red', 'No se pudo conectar con el servidor.', 'error');
    });
}
</script>
</body>
</html>