<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/limpiar_espacio_error.log');

/**
 * LIMPIADOR MASIVO DE ESPACIO EN DISCO - SUBDOMINIOS SIE
 * =======================================================
 * Escanea cada subdominio DokuWiki y detecta basura que puede eliminarse
 * de forma segura para liberar espacio en disco.
 *
 * CATEGORIAS DE LIMPIEZA:
 *   1. data/cache     - Cache de DokuWiki (se regenera automaticamente)
 *   2. data/attic     - Historial de versiones (revisiones antiguas de paginas)
 *   3. data/media_attic - Historial de versiones de archivos media
 *   4. data/tmp       - Archivos temporales
 *   5. data/log       - Logs internos de DokuWiki (deprecated.log, debug.log)
 *   6. *.bak_*        - Backups creados por otros diagnosticos
 *   7. error_log      - Logs de error de PHP en cada subdominio
 *
 * MODOS:
 *   ?modo=escanear     (default) - Solo muestra espacio recuperable, NO borra nada
 *   ?modo=limpiar                - Ejecuta la limpieza de categorias seleccionadas
 *   ?cats=cache,attic,tmp,...    - Categorias a limpiar (comma separated)
 *   ?sub=nombre                  - Solo un subdominio
 *   ?attic_dias=90               - Solo borrar attic mas viejo que N dias (default 90)
 *   ?orden=peso|nombre           - Ordenar resultados
 *
 * SEGURIDAD:
 *   - Modo escanear NO modifica nada
 *   - Solo borra lo que esta en las categorias seleccionadas
 *   - data/attic se filtra por antigüedad (default: >90 dias)
 *   - NUNCA toca data/pages, data/media (archivos reales), conf/, lib/
 */

// =====================================================================
//  CONFIGURACION
// =====================================================================

$basePath = '/home/systeng3/public_html';

$excluir = ['.', '..', 'cgi-bin', '.well-known', '.trash', '.htaccess',
            'respaldo', 'diagnosticos', 'tmp', 'error_log'];

// Categorias de limpieza disponibles
$categoriasDisponibles = [
    'cache'       => ['label' => 'Cache DokuWiki',          'path' => 'data/cache',       'icon' => '&#128165;', 'risk' => 'bajo',  'desc' => 'Se regenera automaticamente al visitar paginas'],
    'attic'       => ['label' => 'Historial paginas',       'path' => 'data/attic',       'icon' => '&#128214;', 'risk' => 'medio', 'desc' => 'Revisiones antiguas de paginas wiki (filtrado por dias)'],
    'media_attic' => ['label' => 'Historial media',         'path' => 'data/media_attic', 'icon' => '&#128247;', 'risk' => 'medio', 'desc' => 'Versiones anteriores de archivos subidos'],
    'tmp'         => ['label' => 'Temporales',              'path' => 'data/tmp',         'icon' => '&#128465;', 'risk' => 'bajo',  'desc' => 'Archivos temporales de DokuWiki'],
    'log'         => ['label' => 'Logs DokuWiki',           'path' => 'data/log',         'icon' => '&#128196;', 'risk' => 'bajo',  'desc' => 'deprecated.log, debug.log, etc.'],
    'bak'         => ['label' => 'Backups diagnosticos',    'path' => '*',                'icon' => '&#128230;', 'risk' => 'bajo',  'desc' => 'Archivos .bak_* creados por otros diagnosticos'],
    'errorlog'    => ['label' => 'error_log PHP',           'path' => 'error_log',        'icon' => '&#128680;', 'risk' => 'bajo',  'desc' => 'Logs de error PHP en raiz de cada subdominio'],
];

// =====================================================================
//  PARAMETROS
// =====================================================================

$esCLI = (php_sapi_name() === 'cli');
if (!$esCLI) header('Content-Type: text/html; charset=UTF-8');

@set_time_limit(600);
@ini_set('max_execution_time', 600);
@ini_set('memory_limit', '512M');

$modo      = $esCLI ? ($argv[1] ?? 'escanear') : ($_GET['modo'] ?? 'escanear');
$targetSub = $esCLI ? ($argv[2] ?? '')          : ($_GET['sub'] ?? '');
$orden     = $esCLI ? ($argv[3] ?? 'peso')      : ($_GET['orden'] ?? 'peso');
$atticDias = intval($esCLI ? ($argv[4] ?? 90) : ($_GET['attic_dias'] ?? 90));
$catsParam = $esCLI ? ($argv[5] ?? '')          : ($_GET['cats'] ?? '');

if ($atticDias < 1) $atticDias = 90;

// Categorias seleccionadas para limpiar
$catsSeleccionadas = [];
if (!empty($catsParam)) {
    $catsSeleccionadas = array_intersect(explode(',', $catsParam), array_keys($categoriasDisponibles));
}

if (!empty($targetSub)) {
    if (preg_match('#^https?://#i', $targetSub)) {
        $parsed = parse_url($targetSub);
        if (isset($parsed['host'])) {
            $parts = explode('.', $parsed['host']);
            $targetSub = $parts[0];
        }
    }
    $targetSub = basename(preg_replace('/[^a-zA-Z0-9._-]/', '', $targetSub));
}

// =====================================================================
//  FUNCIONES
// =====================================================================

function formatBytes($bytes, $decimals = 2)
{
    if ($bytes <= 0) return '0 B';
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $i = floor(log($bytes, 1024));
    return round($bytes / pow(1024, $i), $decimals) . ' ' . $units[$i];
}

/**
 * Calcula tamaño de una carpeta completa
 */
function dirSize($dir)
{
    if (!is_dir($dir)) return ['size' => 0, 'files' => 0];
    $size = 0; $files = 0;
    $it = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::LEAVES_ONLY
    );
    foreach ($it as $f) {
        if ($f->isFile()) { $size += $f->getSize(); $files++; }
    }
    return ['size' => $size, 'files' => $files];
}

/**
 * Calcula tamaño de archivos en attic mas viejos que N dias
 */
function atticSizeOld($dir, $dias)
{
    if (!is_dir($dir)) return ['size' => 0, 'files' => 0, 'total_size' => 0, 'total_files' => 0];
    $cutoff = time() - ($dias * 86400);
    $size = 0; $files = 0; $totalSize = 0; $totalFiles = 0;
    $it = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::LEAVES_ONLY
    );
    foreach ($it as $f) {
        if ($f->isFile()) {
            $totalSize += $f->getSize();
            $totalFiles++;
            if ($f->getMTime() < $cutoff) {
                $size += $f->getSize();
                $files++;
            }
        }
    }
    return ['size' => $size, 'files' => $files, 'total_size' => $totalSize, 'total_files' => $totalFiles];
}

/**
 * Busca archivos .bak_* en un subdominio
 */
function buscarBackups($subPath)
{
    $size = 0; $files = 0; $lista = [];
    // Buscar en conf/ y data/
    $dirs = ['conf', 'data/meta', 'data/pages'];
    foreach ($dirs as $d) {
        $fullDir = $subPath . '/' . $d;
        if (!is_dir($fullDir)) continue;
        $it = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($fullDir, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::LEAVES_ONLY
        );
        foreach ($it as $f) {
            if ($f->isFile() && preg_match('/\.bak_/', $f->getFilename())) {
                $size += $f->getSize();
                $files++;
                $lista[] = $f->getPathname();
            }
        }
    }
    // Buscar en raiz del subdominio
    $scan = @scandir($subPath);
    if ($scan) {
        foreach ($scan as $item) {
            if (preg_match('/\.bak_/', $item) && is_file($subPath . '/' . $item)) {
                $size += filesize($subPath . '/' . $item);
                $files++;
                $lista[] = $subPath . '/' . $item;
            }
        }
    }
    return ['size' => $size, 'files' => $files, 'lista' => $lista];
}

/**
 * Tamaño del archivo error_log en raiz
 */
function errorLogSize($subPath)
{
    $file = $subPath . '/error_log';
    if (!is_file($file)) return ['size' => 0, 'files' => 0];
    return ['size' => filesize($file), 'files' => 1];
}

/**
 * Elimina recursivamente el contenido de una carpeta (no la carpeta misma)
 */
function limpiarCarpeta($dir)
{
    if (!is_dir($dir)) return ['deleted' => 0, 'freed' => 0, 'errors' => 0];
    $deleted = 0; $freed = 0; $errors = 0;
    $it = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($it as $f) {
        if ($f->isDir()) {
            @rmdir($f->getPathname());
        } else {
            $s = $f->getSize();
            if (@unlink($f->getPathname())) {
                $deleted++; $freed += $s;
            } else {
                $errors++;
            }
        }
    }
    return ['deleted' => $deleted, 'freed' => $freed, 'errors' => $errors];
}

/**
 * Elimina archivos en attic mas viejos que N dias
 */
function limpiarAtticViejo($dir, $dias)
{
    if (!is_dir($dir)) return ['deleted' => 0, 'freed' => 0, 'errors' => 0];
    $cutoff = time() - ($dias * 86400);
    $deleted = 0; $freed = 0; $errors = 0;
    $it = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::LEAVES_ONLY
    );
    $toDelete = [];
    foreach ($it as $f) {
        if ($f->isFile() && $f->getMTime() < $cutoff) {
            $toDelete[] = ['path' => $f->getPathname(), 'size' => $f->getSize()];
        }
    }
    foreach ($toDelete as $td) {
        if (@unlink($td['path'])) {
            $deleted++; $freed += $td['size'];
        } else {
            $errors++;
        }
    }
    // Limpiar carpetas vacias
    $it2 = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($it2 as $f) {
        if ($f->isDir()) @rmdir($f->getPathname());
    }
    return ['deleted' => $deleted, 'freed' => $freed, 'errors' => $errors];
}

/**
 * Elimina archivos .bak_* de un subdominio
 */
function limpiarBackups($lista)
{
    $deleted = 0; $freed = 0; $errors = 0;
    foreach ($lista as $file) {
        if (is_file($file)) {
            $s = filesize($file);
            if (@unlink($file)) {
                $deleted++; $freed += $s;
            } else {
                $errors++;
            }
        }
    }
    return ['deleted' => $deleted, 'freed' => $freed, 'errors' => $errors];
}

/**
 * Analiza un subdominio y calcula espacio recuperable por categoria
 */
function analizarSubdominio($subPath, $carpeta, $atticDias, $categoriasDisponibles)
{
    $r = [
        'carpeta'    => $carpeta,
        'tiene_doku' => false,
        'total_size' => 0,
        'categorias' => [],
        'total_recuperable' => 0,
    ];

    if (!file_exists($subPath . '/doku.php')) return $r;
    $r['tiene_doku'] = true;

    // Tamaño total del subdominio
    $total = dirSize($subPath);
    $r['total_size'] = $total['size'];

    foreach ($categoriasDisponibles as $catKey => $catInfo) {
        switch ($catKey) {
            case 'cache':
            case 'tmp':
            case 'log':
                $info = dirSize($subPath . '/' . $catInfo['path']);
                $r['categorias'][$catKey] = $info;
                $r['total_recuperable'] += $info['size'];
                break;

            case 'attic':
            case 'media_attic':
                $info = atticSizeOld($subPath . '/' . $catInfo['path'], $atticDias);
                $r['categorias'][$catKey] = $info;
                $r['total_recuperable'] += $info['size'];
                break;

            case 'bak':
                $info = buscarBackups($subPath);
                $r['categorias'][$catKey] = $info;
                $r['total_recuperable'] += $info['size'];
                break;

            case 'errorlog':
                $info = errorLogSize($subPath);
                $r['categorias'][$catKey] = $info;
                $r['total_recuperable'] += $info['size'];
                break;
        }
    }

    return $r;
}

// =====================================================================
//  EJECUCION
// =====================================================================

$tiempoInicio = microtime(true);
$resultados   = [];
$resumenLimpieza = [];

// Obtener lista de carpetas
if (!empty($targetSub)) {
    $carpetas = [$targetSub];
} else {
    $carpetas = [];
    $scan = @scandir($basePath);
    if (!$scan) {
        echo $esCLI ? "ERROR: No se puede leer {$basePath}\n" : "<p style='color:red'>ERROR: No se puede leer {$basePath}</p>";
        exit(1);
    }
    foreach ($scan as $c) {
        if (in_array($c, $excluir)) continue;
        if (!is_dir($basePath . '/' . $c)) continue;
        $carpetas[] = $c;
    }
    sort($carpetas);
}

// =====================================================================
//  MODO LIMPIAR
// =====================================================================

if ($modo === 'limpiar' && !empty($catsSeleccionadas)) {
    foreach ($carpetas as $carpeta) {
        $subPath = $basePath . '/' . $carpeta;
        if (!file_exists($subPath . '/doku.php')) continue;

        $subResult = ['carpeta' => $carpeta, 'acciones' => []];

        foreach ($catsSeleccionadas as $cat) {
            switch ($cat) {
                case 'cache':
                case 'tmp':
                case 'log':
                    $path = $subPath . '/' . $categoriasDisponibles[$cat]['path'];
                    $res = limpiarCarpeta($path);
                    $subResult['acciones'][$cat] = $res;
                    break;

                case 'attic':
                case 'media_attic':
                    $path = $subPath . '/' . $categoriasDisponibles[$cat]['path'];
                    $res = limpiarAtticViejo($path, $atticDias);
                    $subResult['acciones'][$cat] = $res;
                    break;

                case 'bak':
                    $bakInfo = buscarBackups($subPath);
                    $res = limpiarBackups($bakInfo['lista']);
                    $subResult['acciones'][$cat] = $res;
                    break;

                case 'errorlog':
                    $file = $subPath . '/error_log';
                    if (is_file($file)) {
                        $s = filesize($file);
                        if (@unlink($file)) {
                            $subResult['acciones'][$cat] = ['deleted' => 1, 'freed' => $s, 'errors' => 0];
                        } else {
                            $subResult['acciones'][$cat] = ['deleted' => 0, 'freed' => 0, 'errors' => 1];
                        }
                    } else {
                        $subResult['acciones'][$cat] = ['deleted' => 0, 'freed' => 0, 'errors' => 0];
                    }
                    break;
            }
        }
        $resumenLimpieza[] = $subResult;
    }
}

// =====================================================================
//  MODO ESCANEAR (siempre, para mostrar estado actual)
// =====================================================================

foreach ($carpetas as $carpeta) {
    $subPath = $basePath . '/' . $carpeta;
    $r = analizarSubdominio($subPath, $carpeta, $atticDias, $categoriasDisponibles);
    if (!$r['tiene_doku']) continue;
    $resultados[] = $r;
}

// Ordenar
if ($orden === 'peso') {
    usort($resultados, fn($a, $b) => $b['total_recuperable'] - $a['total_recuperable']);
} elseif ($orden === 'nombre') {
    usort($resultados, fn($a, $b) => strcasecmp($a['carpeta'], $b['carpeta']));
} elseif ($orden === 'total') {
    usort($resultados, fn($a, $b) => $b['total_size'] - $a['total_size']);
}

$tiempoFin = round(microtime(true) - $tiempoInicio, 2);

// Estadisticas globales
$totalSistemasCount = count($resultados);
$totalSizeAll       = array_sum(array_column($resultados, 'total_size'));
$totalRecuperable   = array_sum(array_column($resultados, 'total_recuperable'));

// Por categoria
$totalPorCat = [];
foreach (array_keys($categoriasDisponibles) as $catKey) {
    $totalPorCat[$catKey] = 0;
    foreach ($resultados as $r) {
        $totalPorCat[$catKey] += $r['categorias'][$catKey]['size'] ?? 0;
    }
}

// Totales de limpieza ejecutada
$totalLimpiado = 0;
$totalArchivosEliminados = 0;
$totalErrores = 0;
foreach ($resumenLimpieza as $sl) {
    foreach ($sl['acciones'] as $act) {
        $totalLimpiado += $act['freed'];
        $totalArchivosEliminados += $act['deleted'];
        $totalErrores += $act['errors'];
    }
}

// =====================================================================
//  SALIDA CLI
// =====================================================================

if ($esCLI) {
    echo "================================================================\n";
    echo " LIMPIADOR DE ESPACIO - SUBDOMINIOS SIE\n";
    echo " " . date('Y-m-d H:i:s') . " | Tiempo: {$tiempoFin}s\n";
    echo "================================================================\n\n";

    echo "Sistemas: {$totalSistemasCount} | Total disco: " . formatBytes($totalSizeAll) . " | Recuperable: " . formatBytes($totalRecuperable) . "\n\n";

    foreach ($resultados as $r) {
        echo sprintf("  %-30s %10s  recup: %10s\n",
            $r['carpeta'], formatBytes($r['total_size']), formatBytes($r['total_recuperable']));
    }
    exit(0);
}

// =====================================================================
//  SALIDA HTML
// =====================================================================
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Limpiador de Espacio - SIE</title>
<style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f1f5f9; color: #1e293b; padding: 20px; }
    .container { max-width: 1500px; margin: 0 auto; }
    h1 { font-size: 1.5em; color: #0f172a; margin-bottom: 4px; }
    .subtitle { color: #64748b; font-size: 0.88em; margin-bottom: 20px; }

    .summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 20px; }
    .card { background: #fff; border-radius: 10px; padding: 14px; text-align: center; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
    .card .num { font-size: 1.5em; font-weight: 700; }
    .card .label { font-size: 0.78em; color: #64748b; margin-top: 2px; }
    .green { color: #16a34a; } .red { color: #dc2626; } .yellow { color: #d97706; } .blue { color: #2563eb; } .purple { color: #7c3aed; } .orange { color: #ea580c; }

    .section { background: #fff; border-radius: 10px; padding: 20px; margin-bottom: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
    .section h2 { font-size: 1.1em; margin-bottom: 12px; }

    .explain { background: #fef3c7; border: 1px solid #fbbf24; border-radius: 10px; padding: 16px; margin-bottom: 20px; }
    .explain h2 { color: #92400e; margin-bottom: 8px; font-size: 1em; }
    .explain p { font-size: 0.86em; color: #78350f; margin-bottom: 4px; }

    .success-box { background: #dcfce7; border: 1px solid #86efac; border-radius: 10px; padding: 16px; margin-bottom: 20px; }
    .success-box h2 { color: #166534; margin-bottom: 8px; font-size: 1em; }
    .success-box p { font-size: 0.86em; color: #14532d; margin-bottom: 4px; }

    .actions { display: flex; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; align-items: center; }
    .btn { padding: 10px 20px; border: none; border-radius: 8px; font-size: 0.9em; cursor: pointer; text-decoration: none; display: inline-block; font-weight: 600; }
    .btn-blue { background: #2563eb; color: #fff; } .btn-blue:hover { background: #1d4ed8; }
    .btn-red { background: #dc2626; color: #fff; } .btn-red:hover { background: #b91c1c; }
    .btn-green { background: #16a34a; color: #fff; } .btn-green:hover { background: #15803d; }
    .btn-gray { background: #64748b; color: #fff; }
    .btn-active { background: #0f172a; color: #fff; }
    .btn-outline { background: transparent; border: 2px solid #2563eb; color: #2563eb; }

    .cat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 20px; }
    .cat-card { background: #fff; border-radius: 10px; padding: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); border-left: 4px solid #94a3b8; cursor: pointer; transition: all 0.2s; }
    .cat-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.12); }
    .cat-card.selected { border-left-color: #2563eb; background: #eff6ff; }
    .cat-card .icon { font-size: 1.5em; }
    .cat-card .name { font-size: 0.95em; font-weight: 700; margin: 4px 0; }
    .cat-card .size { font-size: 1.3em; font-weight: 700; color: #dc2626; }
    .cat-card .desc { font-size: 0.76em; color: #64748b; margin-top: 4px; }
    .cat-card .risk { display: inline-block; padding: 1px 6px; border-radius: 3px; font-size: 0.7em; font-weight: 600; margin-top: 4px; }
    .risk-bajo { background: #dcfce7; color: #166534; }
    .risk-medio { background: #fef3c7; color: #92400e; }

    table { width: 100%; border-collapse: collapse; font-size: 0.82em; }
    th { text-align: left; padding: 8px 6px; border-bottom: 2px solid #e2e8f0; color: #475569; font-size: 0.82em; }
    td { padding: 7px 6px; border-bottom: 1px solid #f1f5f9; }
    tr:hover { background: #f8fafc; }

    .bar-container { width: 100%; height: 8px; background: #e2e8f0; border-radius: 4px; overflow: hidden; }
    .bar-fill { height: 100%; border-radius: 4px; background: #ef4444; }

    .badge { display: inline-block; padding: 2px 7px; border-radius: 4px; font-size: 0.76em; font-weight: 600; }
    .badge-heavy { background: #fee2e2; color: #991b1b; }
    .badge-medium { background: #fef3c7; color: #92400e; }
    .badge-light { background: #dcfce7; color: #166534; }

    .filter-bar { margin-bottom: 12px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
    .filter-bar input { padding: 6px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 0.86em; width: 200px; }

    .chk { width: 18px; height: 18px; accent-color: #2563eb; }
    .confirm-box { background: #fef2f2; border: 2px solid #dc2626; border-radius: 10px; padding: 20px; margin: 20px 0; display: none; }
</style>
</head>
<body>
<div class="container">

<h1>&#128465; Limpiador de Espacio en Disco - SIE</h1>
<p class="subtitle">
    <?= date('Y-m-d H:i:s') ?> |
    Tiempo: <?= $tiempoFin ?>s |
    Sistemas: <?= $totalSistemasCount ?>
    <?php if (!empty($targetSub)): ?> | Sub: <strong><?= htmlspecialchars($targetSub) ?></strong><?php endif; ?>
    | Attic: &gt;<?= $atticDias ?> dias
</p>

<?php if ($modo === 'limpiar' && !empty($resumenLimpieza)): ?>
<!-- ============ RESULTADO DE LIMPIEZA ============ -->
<div class="success-box">
    <h2>&#9989; Limpieza completada</h2>
    <p><strong>Espacio liberado:</strong> <?= formatBytes($totalLimpiado) ?></p>
    <p><strong>Archivos eliminados:</strong> <?= number_format($totalArchivosEliminados) ?></p>
    <?php if ($totalErrores > 0): ?>
    <p style="color:#dc2626;"><strong>Errores:</strong> <?= $totalErrores ?> archivos no se pudieron eliminar (permisos)</p>
    <?php endif; ?>
    <p style="margin-top:8px;"><strong>Categorias limpiadas:</strong> <?= implode(', ', array_map(fn($c) => $categoriasDisponibles[$c]['label'], $catsSeleccionadas)) ?></p>
</div>

<?php if (count($resumenLimpieza) > 0): ?>
<div class="section">
    <h2>Detalle por subdominio</h2>
    <table>
        <thead><tr><th>#</th><th>Subdominio</th>
        <?php foreach ($catsSeleccionadas as $cat): ?>
            <th><?= $categoriasDisponibles[$cat]['label'] ?></th>
        <?php endforeach; ?>
        <th>Total liberado</th><th>Errores</th></tr></thead>
        <tbody>
        <?php $i = 0; foreach ($resumenLimpieza as $sl): $i++;
            $subFreed = 0; $subErrors = 0;
            foreach ($sl['acciones'] as $act) { $subFreed += $act['freed']; $subErrors += $act['errors']; }
            if ($subFreed === 0 && $subErrors === 0) continue;
        ?>
            <tr>
                <td><?= $i ?></td>
                <td><strong><?= htmlspecialchars($sl['carpeta']) ?></strong></td>
                <?php foreach ($catsSeleccionadas as $cat): ?>
                    <td><?= formatBytes($sl['acciones'][$cat]['freed'] ?? 0) ?> <span style="color:#94a3b8;font-size:0.85em;">(<?= $sl['acciones'][$cat]['deleted'] ?? 0 ?>)</span></td>
                <?php endforeach; ?>
                <td><strong style="color:#16a34a;"><?= formatBytes($subFreed) ?></strong></td>
                <td><?= $subErrors > 0 ? '<span style="color:#dc2626;">' . $subErrors . '</span>' : '0' ?></td>
            </tr>
        <?php endforeach; ?>
        </tbody>
    </table>
</div>
<?php endif; ?>
<?php endif; ?>

<div class="explain">
    <h2>&#9888;&#65039; Que hace esta herramienta</h2>
    <p>Identifica y elimina basura acumulada en los subdominios DokuWiki: cache, historial antiguo, temporales, logs y backups.</p>
    <p><strong>Paso 1:</strong> Revisa el escaneo (abajo) para ver cuanto espacio se puede liberar por categoria.</p>
    <p><strong>Paso 2:</strong> Selecciona las categorias que quieres limpiar y haz clic en "Ejecutar limpieza".</p>
    <p><strong>Riesgo bajo:</strong> Cache, temporales, logs y backups se pueden borrar sin consecuencias.</p>
    <p><strong>Riesgo medio:</strong> Attic (historial) — se pierden revisiones antiguas. Solo borra versiones de mas de <?= $atticDias ?> dias.</p>
</div>

<!-- Resumen global -->
<div class="summary">
    <div class="card"><div class="num blue"><?= $totalSistemasCount ?></div><div class="label">Sistemas DokuWiki</div></div>
    <div class="card"><div class="num purple"><?= formatBytes($totalSizeAll) ?></div><div class="label">Peso Total</div></div>
    <div class="card"><div class="num red"><?= formatBytes($totalRecuperable) ?></div><div class="label">Espacio Recuperable</div></div>
    <div class="card"><div class="num green"><?= $totalSizeAll > 0 ? round(($totalRecuperable / $totalSizeAll) * 100, 1) : 0 ?>%</div><div class="label">% Recuperable</div></div>
    <?php if ($totalLimpiado > 0): ?>
    <div class="card" style="border:2px solid #16a34a;"><div class="num green"><?= formatBytes($totalLimpiado) ?></div><div class="label">Liberado ahora</div></div>
    <?php endif; ?>
</div>

<!-- Categorias como cards seleccionables -->
<div class="section">
    <h2>&#128204; Categorias de limpieza (espacio total recuperable por tipo)</h2>
    <form id="formLimpieza" method="GET">
        <input type="hidden" name="modo" value="limpiar">
        <?php if (!empty($targetSub)): ?>
            <input type="hidden" name="sub" value="<?= htmlspecialchars($targetSub) ?>">
        <?php endif; ?>
        <input type="hidden" name="attic_dias" value="<?= $atticDias ?>">
        <input type="hidden" name="cats" id="catsInput" value="">

        <div class="cat-grid">
        <?php foreach ($categoriasDisponibles as $catKey => $catInfo): ?>
            <div class="cat-card" id="cat-<?= $catKey ?>" onclick="toggleCat('<?= $catKey ?>')">
                <div style="display:flex;justify-content:space-between;align-items:center;">
                    <span class="icon"><?= $catInfo['icon'] ?></span>
                    <input type="checkbox" class="chk" id="chk-<?= $catKey ?>" onclick="event.stopPropagation(); toggleCat('<?= $catKey ?>')">
                </div>
                <div class="name"><?= $catInfo['label'] ?></div>
                <div class="size"><?= formatBytes($totalPorCat[$catKey]) ?></div>
                <div class="desc"><?= $catInfo['desc'] ?></div>
                <span class="risk risk-<?= $catInfo['risk'] ?>"><?= strtoupper($catInfo['risk']) ?></span>
            </div>
        <?php endforeach; ?>
        </div>

        <div style="display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:12px;">
            <button type="button" class="btn btn-blue" onclick="seleccionarBajoRiesgo()">Seleccionar riesgo bajo</button>
            <button type="button" class="btn btn-outline" onclick="seleccionarTodo()">Seleccionar todo</button>
            <button type="button" class="btn btn-gray" onclick="deseleccionarTodo()">Deseleccionar todo</button>
            <span style="color:#64748b;font-size:0.85em;">|</span>
            <label style="font-size:0.86em;">Attic mas viejo que:
                <input type="number" name="attic_dias" value="<?= $atticDias ?>" min="7" max="365" style="width:60px;padding:4px;border:1px solid #cbd5e1;border-radius:4px;"> dias
            </label>
        </div>

        <div class="confirm-box" id="confirmBox">
            <h3 style="color:#dc2626;margin-bottom:8px;">&#9888;&#65039; Confirmar limpieza</h3>
            <p style="font-size:0.9em;margin-bottom:12px;">Se van a eliminar archivos de <strong id="confirmCount">0</strong> sistemas en las categorias seleccionadas. Esta accion <strong>no se puede deshacer</strong>.</p>
            <p style="font-size:0.9em;margin-bottom:16px;">Espacio estimado a liberar: <strong id="confirmSize" style="color:#16a34a;">0 B</strong></p>
            <div style="display:flex;gap:12px;">
                <button type="submit" class="btn btn-red">&#128465; SI, ejecutar limpieza</button>
                <button type="button" class="btn btn-gray" onclick="document.getElementById('confirmBox').style.display='none'">Cancelar</button>
            </div>
        </div>

        <div style="margin-top:16px;">
            <button type="button" class="btn btn-red" onclick="confirmarLimpieza()">&#128465; Ejecutar limpieza</button>
        </div>
    </form>
</div>

<!-- Botones de orden -->
<div class="actions">
    <a href="?orden=peso<?= !empty($targetSub) ? '&sub=' . urlencode($targetSub) : '' ?>&attic_dias=<?= $atticDias ?>" class="btn <?= $orden === 'peso' ? 'btn-active' : 'btn-blue' ?>">&#128201; Por espacio recuperable</a>
    <a href="?orden=total<?= !empty($targetSub) ? '&sub=' . urlencode($targetSub) : '' ?>&attic_dias=<?= $atticDias ?>" class="btn <?= $orden === 'total' ? 'btn-active' : 'btn-blue' ?>">&#128202; Por peso total</a>
    <a href="?orden=nombre<?= !empty($targetSub) ? '&sub=' . urlencode($targetSub) : '' ?>&attic_dias=<?= $atticDias ?>" class="btn <?= $orden === 'nombre' ? 'btn-active' : 'btn-blue' ?>">&#128196; Por nombre</a>
    <?php if (!empty($targetSub)): ?>
        <a href="?attic_dias=<?= $atticDias ?>" class="btn btn-gray">Ver todos</a>
    <?php endif; ?>
</div>

<!-- ============ TABLA COMPLETA ============ -->
<div class="section">
    <h2>&#128203; Todos los sistemas (<?= $totalSistemasCount ?>)</h2>
    <div class="filter-bar">
        <input type="text" id="filtro" placeholder="Buscar subdominio..." oninput="filtrar()">
    </div>
    <div style="overflow-x:auto;">
    <table id="tabla">
        <thead>
            <tr>
                <th>#</th>
                <th>Subdominio</th>
                <th>Peso Total</th>
                <th>Recuperable</th>
                <th>Cache</th>
                <th>Attic &gt;<?= $atticDias ?>d</th>
                <th>Media Attic</th>
                <th>Tmp</th>
                <th>Logs</th>
                <th>Bak</th>
                <th>error_log</th>
                <th>% Basura</th>
            </tr>
        </thead>
        <tbody>
        <?php $i = 0; foreach ($resultados as $r): $i++;
            $pctBasura = $r['total_size'] > 0 ? round(($r['total_recuperable'] / $r['total_size']) * 100, 1) : 0;
            if ($pctBasura > 30) { $catClass = 'badge-heavy'; }
            elseif ($pctBasura > 10) { $catClass = 'badge-medium'; }
            else { $catClass = 'badge-light'; }
        ?>
            <tr data-name="<?= htmlspecialchars(strtolower($r['carpeta'])) ?>">
                <td><?= $i ?></td>
                <td>
                    <a href="?sub=<?= urlencode($r['carpeta']) ?>&attic_dias=<?= $atticDias ?>" style="font-weight:700;color:#1e40af;text-decoration:none;">
                        <?= htmlspecialchars($r['carpeta']) ?>
                    </a>
                </td>
                <td><strong><?= formatBytes($r['total_size']) ?></strong></td>
                <td><strong style="color:#dc2626;"><?= formatBytes($r['total_recuperable']) ?></strong></td>
                <td><?= formatBytes($r['categorias']['cache']['size'] ?? 0) ?></td>
                <td><?= formatBytes($r['categorias']['attic']['size'] ?? 0) ?>
                    <?php if (($r['categorias']['attic']['total_size'] ?? 0) > 0): ?>
                    <span style="color:#94a3b8;font-size:0.8em;">/<?= formatBytes($r['categorias']['attic']['total_size']) ?></span>
                    <?php endif; ?>
                </td>
                <td><?= formatBytes($r['categorias']['media_attic']['size'] ?? 0) ?></td>
                <td><?= formatBytes($r['categorias']['tmp']['size'] ?? 0) ?></td>
                <td><?= formatBytes($r['categorias']['log']['size'] ?? 0) ?></td>
                <td><?= formatBytes($r['categorias']['bak']['size'] ?? 0) ?></td>
                <td><?= formatBytes($r['categorias']['errorlog']['size'] ?? 0) ?></td>
                <td>
                    <span class="badge <?= $catClass ?>"><?= $pctBasura ?>%</span>
                    <div class="bar-container" style="margin-top:3px;">
                        <div class="bar-fill" style="width:<?= min($pctBasura, 100) ?>%"></div>
                    </div>
                </td>
            </tr>
        <?php endforeach; ?>
        </tbody>
    </table>
    </div>
</div>

</div><!-- /container -->

<script>
var selectedCats = {};

function toggleCat(key) {
    var card = document.getElementById('cat-' + key);
    var chk = document.getElementById('chk-' + key);
    if (selectedCats[key]) {
        delete selectedCats[key];
        card.classList.remove('selected');
        chk.checked = false;
    } else {
        selectedCats[key] = true;
        card.classList.add('selected');
        chk.checked = true;
    }
    updateCatsInput();
}

function updateCatsInput() {
    document.getElementById('catsInput').value = Object.keys(selectedCats).join(',');
}

function seleccionarBajoRiesgo() {
    deseleccionarTodo();
    ['cache', 'tmp', 'log', 'bak', 'errorlog'].forEach(function(k) { toggleCat(k); });
}

function seleccionarTodo() {
    deseleccionarTodo();
    <?php foreach (array_keys($categoriasDisponibles) as $k): ?>
    toggleCat('<?= $k ?>');
    <?php endforeach; ?>
}

function deseleccionarTodo() {
    Object.keys(selectedCats).forEach(function(k) {
        var card = document.getElementById('cat-' + k);
        var chk = document.getElementById('chk-' + k);
        if (card) card.classList.remove('selected');
        if (chk) chk.checked = false;
    });
    selectedCats = {};
    updateCatsInput();
}

function confirmarLimpieza() {
    var cats = Object.keys(selectedCats);
    if (cats.length === 0) {
        alert('Selecciona al menos una categoria para limpiar');
        return;
    }
    document.getElementById('confirmCount').textContent = '<?= $totalSistemasCount ?>';
    // Calcular estimado
    var total = 0;
    <?php foreach ($categoriasDisponibles as $k => $v): ?>
    if (selectedCats['<?= $k ?>']) total += <?= $totalPorCat[$k] ?>;
    <?php endforeach; ?>
    document.getElementById('confirmSize').textContent = formatBytesJS(total);
    document.getElementById('confirmBox').style.display = 'block';
    document.getElementById('confirmBox').scrollIntoView({behavior:'smooth'});
}

function formatBytesJS(bytes) {
    if (bytes <= 0) return '0 B';
    var units = ['B', 'KB', 'MB', 'GB', 'TB'];
    var i = Math.floor(Math.log(bytes) / Math.log(1024));
    return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + units[i];
}

function filtrar() {
    var texto = document.getElementById('filtro').value.toLowerCase();
    var rows = document.querySelectorAll('#tabla tbody tr');
    rows.forEach(function(row) {
        var name = row.dataset.name || '';
        row.style.display = (!texto || name.indexOf(texto) !== -1) ? '' : 'none';
    });
}
</script>
</body>
</html>
