<?php
require_once __DIR__ . '/auth.php';
/**
 * Backup SIE - copiar.php
 * ========================
 * Recorre cada subdominio DokuWiki y respalda archivos clave
 * en respaldo/{subdominio}.zip
 *
 * NO aplican exclusiones: se procesan TODOS los subdominios.
 * Procesa UN subdominio por ejecucion para evitar timeouts.
 * Auto-continua al siguiente con meta-refresh de 1 segundo.
 * Opcion de incluir o no los archivos media (data/media y data/pages).
 *
 * Uso: copiar.php              -> Pantalla inicial con opciones
 *      copiar.php?i=5&media=1  -> Procesa subdominio #5 con media
 *      copiar.php?reset=1      -> Reinicia el progreso
 */

require_once __DIR__ . '/config.php';

set_time_limit(MAX_EXECUTION_TIME);
ini_set('memory_limit', MEMORY_LIMIT);
@ini_set('output_buffering', 'Off');
@ini_set('zlib.output_compression', 'Off');

// ============================================================
// FUNCIONES DE ESCANEO (patron probado NICC)
// ============================================================

/**
 * Escanea SOLO el nivel inmediato de $path buscando instalaciones DokuWiki.
 * No recursa en subdirectorios para evitar duplicados.
 */
function scanDirectory($path) {
    $sites = [];
    if (!is_dir($path)) return $sites;

    $items = @scandir($path);
    if ($items === false) return $sites;

    foreach ($items as $item) {
        if ($item === '.' || $item === '..') continue;
        if ($item[0] === '_') continue;
        $fullPath = $path . '/' . $item;
        if (is_link($fullPath)) continue;
        if (!is_dir($fullPath)) continue;

        // Saltar la carpeta respaldo/ y todo su contenido para no procesarla
        $backupReal = realpath(BACKUP_DIR);
        $fullReal   = realpath($fullPath);
        if ($backupReal && $fullReal && strpos($fullReal, $backupReal) === 0) continue;

        if (isDokuWiki($fullPath)) {
            $sites[] = $fullPath;
        }
    }
    return $sites;
}

function isDokuWiki($path) {
    return file_exists($path . '/doku.php')
        && (file_exists($path . '/conf/local.php') || file_exists($path . '/conf/dokuwiki.php'))
        && is_dir($path . '/data');
}

// ============================================================
// FUNCIONES DE PROGRESO
// ============================================================

function loadProgress() {
    if (file_exists(PROGRESS_FILE)) {
        $data = json_decode(file_get_contents(PROGRESS_FILE), true);
        if (is_array($data)) return $data;
    }
    return [
        'respaldados'             => [],
        'errores'                 => [],
        'detalle'                 => [],
        'archivos_total_copiados' => 0,
        'archivos_no_encontrados' => 0,
        'bytes_total_copiados'    => 0,
        'incluir_media'           => true,
        'letras'                  => '',
        'inicio'                  => date('Y-m-d H:i:s'),
    ];
}

function saveProgress($progress) {
    file_put_contents(PROGRESS_FILE, json_encode($progress, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}

function formatBytes($bytes) {
    if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB';
    if ($bytes >= 1048576)    return number_format($bytes / 1048576, 2) . ' MB';
    if ($bytes >= 1024)       return number_format($bytes / 1024, 2) . ' KB';
    return $bytes . ' bytes';
}

function writeLog($message) {
    file_put_contents(LOG_FILE, date('[Y-m-d H:i:s] ') . $message . "\n", FILE_APPEND);
}

// ============================================================
// FUNCIONES DE COPIA
// ============================================================

/**
 * Agrega recursivamente un directorio completo al ZIP
 * $zip       = objeto ZipArchive abierto
 * $srcDir    = ruta absoluta del directorio fuente
 * $zipPrefix = ruta dentro del ZIP (ej: "data/media")
 */
function addDirToZip($zip, $srcDir, $zipPrefix) {
    $added  = 0;
    $bytes  = 0;
    $errors = [];

    $items = @scandir($srcDir);
    if ($items === false) {
        $errors[] = "No se pudo leer directorio: " . basename($srcDir);
        return [$added, $bytes, $errors];
    }

    foreach ($items as $item) {
        if ($item === '.' || $item === '..') continue;

        $srcPath = $srcDir . '/' . $item;
        $zipPath = $zipPrefix . '/' . $item;

        if (is_dir($srcPath)) {
            list($a, $b, $e) = addDirToZip($zip, $srcPath, $zipPath);
            $added  += $a;
            $bytes  += $b;
            $errors  = array_merge($errors, $e);
        } else {
            $size = @filesize($srcPath) ?: 0;
            if ($zip->addFile($srcPath, $zipPath)) {
                $added++;
                $bytes += $size;
            } else {
                $errors[] = "No se pudo agregar al ZIP: $item";
            }
        }
    }

    return [$added, $bytes, $errors];
}

/**
 * Respalda archivos de un subdominio en ZIP por FASE.
 * Fase 0: crea ZIP nuevo + archivos especificos ($BACKUP_FILES)
 * Fase 1+: abre ZIP existente + carpeta media ($BACKUP_MEDIA_DIRS[fase-1])
 * Retorna: [archivos_agregados, bytes, errores[], archivos_no_encontrados]
 */
function backupSite($sitePath, $includeMedia, $phase = 0) {
    global $BACKUP_FILES, $BACKUP_MEDIA_DIRS, $BACKUP_SMALL_DIRS;

    $siteName = basename($sitePath);
    $zipPath  = BACKUP_DIR . '/' . $siteName . '.zip';

    $added    = 0;
    $bytes    = 0;
    $errors   = [];
    $notFound = 0;

    // Crear carpeta de backup si no existe
    if (!is_dir(BACKUP_DIR)) {
        if (!@mkdir(BACKUP_DIR, 0755, true)) {
            return [0, 0, ["No se pudo crear carpeta backup"], 0];
        }
    }

    $zip = new ZipArchive();

    if ($phase === 0) {
        // FASE 0: Crear ZIP nuevo (borrar anterior si existe)
        if (file_exists($zipPath)) {
            @unlink($zipPath);
        }
        $result = $zip->open($zipPath, ZipArchive::CREATE);
        if ($result !== true) {
            return [0, 0, ["No se pudo crear ZIP: $siteName.zip (error $result)"], 0];
        }

        // Agregar archivos especificos
        foreach ($BACKUP_FILES as $relPath) {
            $srcFile = $sitePath . '/' . $relPath;

            if (!file_exists($srcFile)) {
                $notFound++;
                $errors[] = "No encontrado: $relPath";
                continue;
            }

            $size = @filesize($srcFile) ?: 0;
            if ($zip->addFile($srcFile, $relPath)) {
                $added++;
                $bytes += $size;
            } else {
                $errors[] = "Error al agregar: $relPath";
            }
        }

        // Agregar carpetas pequenas (copia recursiva)
        if (!empty($BACKUP_SMALL_DIRS)) {
            foreach ($BACKUP_SMALL_DIRS as $relDir) {
                $srcDir = $sitePath . '/' . $relDir;
                if (!is_dir($srcDir)) {
                    $notFound++;
                    $errors[] = "No encontrado: $relDir/";
                    continue;
                }
                list($a, $b, $e) = addDirToZip($zip, $srcDir, $relDir);
                $added  += $a;
                $bytes  += $b;
                $errors  = array_merge($errors, $e);
            }
        }

        $zip->close();
    } elseif ($includeMedia) {
        // FASE 1+: Abrir ZIP existente y agregar carpeta media
        $mediaIdx = $phase - 1;
        if ($mediaIdx >= 0 && $mediaIdx < count($BACKUP_MEDIA_DIRS)) {
            $mediaRelDir = $BACKUP_MEDIA_DIRS[$mediaIdx];
            $srcDir = $sitePath . '/' . $mediaRelDir;

            if (!is_dir($srcDir)) {
                $notFound++;
                $errors[] = "Directorio no encontrado: $mediaRelDir";
            } else {
                $result = $zip->open($zipPath, ZipArchive::CREATE);
                if ($result !== true) {
                    return [0, 0, ["No se pudo abrir ZIP: $siteName.zip (error $result)"], 0];
                }

                list($a, $b, $e) = addDirToZip($zip, $srcDir, $mediaRelDir);
                $added  += $a;
                $bytes  += $b;
                $errors  = array_merge($errors, $e);

                $zip->close();
            }
        }
    }

    return [$added, $bytes, $errors, $notFound];
}

// ============================================================
// VERIFICACION INICIAL
// ============================================================

// Crear carpeta de backup si no existe
if (!is_dir(BACKUP_DIR)) {
    @mkdir(BACKUP_DIR, 0755, true);
}

// Calcular tamano total de ZIPs en respaldo/
function getTotalBackupSize() {
    if (!is_dir(BACKUP_DIR)) return 0;
    $total = 0;
    $files = glob(BACKUP_DIR . '/*.zip');
    if ($files) {
        foreach ($files as $f) $total += @filesize($f) ?: 0;
    }
    return $total;
}

$currentBackupSize = getTotalBackupSize();
$backupLimitExceeded = ($currentBackupSize >= MAX_BACKUP_SIZE);

// Reset si se solicita
if (isset($_GET['reset'])) {
    if (file_exists(PROGRESS_FILE)) unlink(PROGRESS_FILE);
    if (file_exists(LOG_FILE)) unlink(LOG_FILE);
    header('Location: copiar.php');
    exit;
}

// Cargar progreso
$progress = loadProgress();

// Escanear TODOS los sitios
$allSites = scanDirectory(SEARCH_PATH);
sort($allSites);
$totalAllSites = count($allSites);

// ============================================================
// DETERMINAR MODO: pantalla inicial o procesamiento
// ============================================================

$showStartScreen = !isset($_GET['i']) && !isset($_GET['start']);

// Parametro media: por defecto activado
$includeMedia = true;
if (isset($_GET['media'])) {
    $includeMedia = ($_GET['media'] === '1');
}

// Parametro letras: string con las letras seleccionadas (ej: "A,B,C" o vacio = todas)
$letrasParam = isset($_GET['letras']) ? trim($_GET['letras']) : '';

// Indice actual y fase
$i     = isset($_GET['i']) ? intval($_GET['i']) : 0;
$phase = isset($_GET['phase']) ? intval($_GET['phase']) : 0;

// Si viene de 'start', verificar limite y guardar preferencias
if (isset($_GET['start']) && $backupLimitExceeded) {
    header('Location: estado.php?msg=' . urlencode('LIMITE ALCANZADO: la carpeta respaldo/ ocupa ' . formatBytes($currentBackupSize) . ' (limite: ' . formatBytes(MAX_BACKUP_SIZE) . '). Descargue los ZIPs y ejecute Limpiar antes de continuar.'));
    exit;
}

if (isset($_GET['start'])) {
    // Recoger letras del formulario (array de checkboxes)
    $letrasArr = isset($_GET['letra']) ? $_GET['letra'] : [];
    $letrasParam = !empty($letrasArr) ? implode(',', $letrasArr) : '';

    $progress['incluir_media'] = $includeMedia;
    $progress['letras'] = $letrasParam;
    saveProgress($progress);

    $logLetras = !empty($letrasParam) ? $letrasParam : 'TODAS';
    writeLog("INICIO BACKUP: media=" . ($includeMedia ? 'SI' : 'NO') . " | letras=$logLetras | $totalAllSites subdominios totales");
    header('Location: copiar.php?i=0&phase=0&media=' . ($includeMedia ? '1' : '0') . '&letras=' . urlencode($letrasParam));
    exit;
}

// Si estamos procesando sin parametros en URL, usar los guardados
if (isset($_GET['i'])) {
    if (!isset($_GET['media'])) {
        $includeMedia = isset($progress['incluir_media']) ? $progress['incluir_media'] : true;
    }
    if (!isset($_GET['letras'])) {
        $letrasParam = isset($progress['letras']) ? $progress['letras'] : '';
    }
}

// ============================================================
// FILTRAR SITIOS POR LETRAS SELECCIONADAS
// ============================================================

$letrasActivas = [];
if (!empty($letrasParam)) {
    $letrasActivas = array_map('strtoupper', array_map('trim', explode(',', $letrasParam)));
}

// Si hay letras seleccionadas, filtrar; si no, usar todos
if (!empty($letrasActivas)) {
    $includeNumbers = in_array('#', $letrasActivas);
    $sites = array_values(array_filter($allSites, function($sitePath) use ($letrasActivas, $includeNumbers) {
        $firstChar = strtoupper(substr(basename($sitePath), 0, 1));
        // Si el primer caracter es un digito, verificar si "#" esta seleccionado
        if (ctype_digit($firstChar)) return $includeNumbers;
        return in_array($firstChar, $letrasActivas);
    }));
} else {
    $sites = $allSites;
}
$totalSites = count($sites);

// ============================================================
// CALCULAR FASES Y SIGUIENTE PASO
// ============================================================
// Fase 0: archivos especificos (siempre)
// Fase 1: data/media (solo si media habilitado)
// Fase 2: data/pages (solo si media habilitado)

global $BACKUP_MEDIA_DIRS;
$maxPhases = 1 + ($includeMedia ? count($BACKUP_MEDIA_DIRS) : 0);

// Calcular siguiente paso (para auto-refresh)
$nextPhase = $phase + 1;
$nextI     = $i;
if ($nextPhase >= $maxPhases) {
    $nextPhase = 0;
    $nextI     = $i + 1;
}

// Etiquetas de fase
$phaseLabels = ['Archivos especificos'];
if ($includeMedia) {
    foreach ($BACKUP_MEDIA_DIRS as $md) {
        $phaseLabels[] = $md;
    }
}
$phaseLabel = isset($phaseLabels[$phase]) ? $phaseLabels[$phase] : '';

// Auto-refresh: continuar si estamos procesando, hay sitios pendientes y no se excedio el limite
$autoRefresh    = !$showStartScreen && ($i < $totalSites) && !$backupLimitExceeded;
$mediaParam     = $includeMedia ? '1' : '0';
$letrasUrlParam = urlencode($letrasParam);

?><!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <?php if ($autoRefresh): ?>
    <meta http-equiv="refresh" content="1;url=copiar.php?i=<?php echo $nextI; ?>&phase=<?php echo $nextPhase; ?>&media=<?php echo $mediaParam; ?>&letras=<?php echo $letrasUrlParam; ?>">
    <?php endif; ?>
    <title>Backup SIE - <?php echo $showStartScreen ? 'Inicio' : (($i + 1) . '/' . $totalSites . ' F' . ($phase + 1) . '/' . $maxPhases); ?></title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: 'Segoe UI', Tahoma, sans-serif; background: #1a1a2e; color: #e0e0e0; padding: 20px; }
        .container { max-width: 900px; margin: 0 auto; }
        h1 { color: #fdcb6e; margin-bottom: 5px; font-size: 1.4em; }
        h2 { color: #ffd93d; font-size: 1.1em; margin: 15px 0 8px; }
        .subtitle { color: #888; font-size: 0.85em; margin-bottom: 15px; }
        .progress-bar { background: #2a2a4a; border-radius: 8px; height: 30px; margin: 10px 0; overflow: hidden; }
        .progress-fill { height: 100%; border-radius: 8px; transition: width 0.3s; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 0.85em; }
        .fill-ok { background: linear-gradient(90deg, #fdcb6e, #f39c12); color: #000; }
        .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 15px 0; }
        .stat-box { background: #2a2a4a; padding: 12px; border-radius: 8px; text-align: center; }
        .stat-value { font-size: 1.5em; font-weight: bold; }
        .stat-label { font-size: 0.8em; color: #888; }
        .val-red { color: #ff6b6b; }
        .val-green { color: #00b894; }
        .val-yellow { color: #ffd93d; }
        .val-blue { color: #74b9ff; }
        .val-purple { color: #a29bfe; }
        .val-orange { color: #fdcb6e; }
        .site-current { background: #2a2a4a; border-left: 4px solid #fdcb6e; padding: 12px; margin: 10px 0; border-radius: 0 8px 8px 0; }
        .site-name { color: #fdcb6e; font-weight: bold; word-break: break-all; }
        .log-box { background: #0d0d1a; border: 1px solid #333; padding: 10px; border-radius: 8px; max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 0.78em; line-height: 1.6; margin: 10px 0; }
        .log-ok { color: #00b894; }
        .log-skip { color: #ffd93d; }
        .log-err { color: #ff6b6b; }
        .log-info { color: #74b9ff; }
        .log-warn { color: #fdcb6e; }
        .btn { display: inline-block; padding: 8px 18px; border-radius: 6px; text-decoration: none; font-weight: bold; font-size: 0.9em; margin: 5px 3px; cursor: pointer; border: none; }
        .btn-primary { background: #0984e3; color: white; }
        .btn-warning { background: #f39c12; color: white; }
        .btn-info { background: #6c5ce7; color: white; }
        .btn-start { background: linear-gradient(90deg, #fdcb6e, #f39c12); color: #000; font-size: 1.1em; padding: 12px 30px; }
        .btn-start:hover { opacity: 0.9; }
        .complete { background: #0d3320; border: 2px solid #00b894; padding: 20px; border-radius: 10px; text-align: center; margin: 20px 0; }
        .complete h2 { color: #00b894; font-size: 1.3em; }
        .warning-box { background: #3d1f00; border: 1px solid #f39c12; padding: 10px; border-radius: 8px; margin: 10px 0; font-size: 0.85em; }
        .start-box { background: #2a1f00; border: 2px solid #fdcb6e; padding: 25px; border-radius: 12px; margin: 20px 0; text-align: center; }
        .start-box h2 { color: #fdcb6e; margin-bottom: 15px; }
        .option-row { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 15px 0; font-size: 1em; }
        .option-row label { cursor: pointer; user-select: none; }
        .toggle { position: relative; display: inline-block; width: 50px; height: 26px; }
        .toggle input { opacity: 0; width: 0; height: 0; }
        .toggle .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #636e72; border-radius: 26px; transition: .3s; }
        .toggle .slider:before { position: absolute; content: ""; height: 20px; width: 20px; left: 3px; bottom: 3px; background-color: white; border-radius: 50%; transition: .3s; }
        .toggle input:checked + .slider { background-color: #fdcb6e; }
        .toggle input:checked + .slider:before { transform: translateX(24px); }
        .media-hint { color: #888; font-size: 0.82em; margin-top: 5px; }
        .mode-tag { display: inline-block; padding: 3px 10px; border-radius: 10px; font-size: 0.75em; font-weight: bold; margin-left: 8px; }
        .mode-tag-on { background: #fdcb6e; color: #000; }
        .mode-tag-off { background: #636e72; color: #fff; }
        .backup-info { background: #1a2a1a; border: 1px solid #00b894; padding: 12px; border-radius: 8px; margin: 10px 0; }
        .letras-grid { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin: 12px 0; }
        .letra-chk { display: none; }
        .letra-label { display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 6px; background: #2a2a4a; color: #aaa; font-weight: bold; font-size: 0.95em; cursor: pointer; transition: all .2s; border: 2px solid transparent; user-select: none; }
        .letra-label:hover { background: #3a3a5a; color: #fff; }
        .letra-chk:checked + .letra-label { background: #fdcb6e; color: #000; border-color: #f39c12; }
        .letras-actions { margin: 8px 0; }
        .letras-actions a { color: #74b9ff; font-size: 0.82em; cursor: pointer; margin: 0 8px; text-decoration: underline; }
        .letras-count { color: #fdcb6e; font-size: 0.85em; margin-top: 5px; }
    </style>
</head>
<body>
<div class="container">
    <h1>Backup SIE</h1>
    <p class="subtitle">Respaldo de archivos clave de cada subdominio DokuWiki</p>

    <!-- Estado del destino -->
    <div class="backup-info">
        <strong>Destino:</strong> respaldo/
        <?php if (is_dir(BACKUP_DIR)): ?>
            (carpeta lista)
        <?php else: ?>
            <span class="log-err">No se pudo crear</span>
        <?php endif; ?>
        &nbsp;|&nbsp;
        <strong>Subdominios:</strong> <?php echo $totalSites; ?> <?php echo ($totalSites < $totalAllSites) ? "de $totalAllSites (filtrados)" : 'encontrados'; ?>
    </div>

<?php if ($showStartScreen): ?>
    <!-- ============================================================ -->
    <!-- PANTALLA INICIAL: opciones antes de ejecutar                  -->
    <!-- ============================================================ -->
    <div class="start-box">
        <h2>Configuracion del Backup</h2>
        <p>Se encontraron <strong><?php echo $totalAllSites; ?></strong> subdominios DokuWiki</p>
        <p style="color: #888; font-size: 0.85em;"><?php echo count($BACKUP_FILES); ?> archivos especificos + <?php echo count($BACKUP_SMALL_DIRS); ?> carpetas config por subdominio + carpetas media opcionales</p>

        <form method="GET" action="copiar.php" style="margin-top: 20px;">
            <input type="hidden" name="start" value="1">

            <div class="option-row">
                <label class="toggle">
                    <input type="hidden" name="media" value="0">
                    <input type="checkbox" name="media" value="1" checked id="chkMedia">
                    <span class="slider"></span>
                </label>
                <label for="chkMedia"><strong>Incluir archivos Media</strong></label>
            </div>
            <div class="media-hint">
                Activado: respalda tambien <code>data/media/</code> y <code>data/pages/</code> (puede ser grande).<br>
                Desactivado: solo respalda archivos especificos (config, templates, plugins, DBs).
            </div>

            <!-- =============================== -->
            <!-- SELECTOR DE LETRAS A-Z          -->
            <!-- =============================== -->
            <h2 style="margin-top: 25px;">Filtrar por letra inicial</h2>
            <p style="color: #888; font-size: 0.82em;">Selecciona las letras de los subdominios a respaldar. Si no seleccionas ninguna, se respaldan TODOS.</p>

            <?php
            // Contar cuantos subdominios empiezan por cada letra o numero
            $conteoLetras = [];
            foreach ($allSites as $s) {
                $ch = strtoupper(substr(basename($s), 0, 1));
                // Agrupar todos los que empiezan con digito bajo "#"
                if (ctype_digit($ch)) $ch = '#';
                if (!isset($conteoLetras[$ch])) $conteoLetras[$ch] = 0;
                $conteoLetras[$ch]++;
            }
            ?>

            <div class="letras-actions">
                <a onclick="document.querySelectorAll('.letra-chk').forEach(c=>c.checked=true);updateCount();">Todas</a>
                <a onclick="document.querySelectorAll('.letra-chk').forEach(c=>c.checked=false);updateCount();">Ninguna</a>
            </div>

            <div class="letras-grid">
            <?php foreach (range('A', 'Z') as $letra): ?>
                <?php $cnt = isset($conteoLetras[$letra]) ? $conteoLetras[$letra] : 0; ?>
                <span>
                    <input type="checkbox" name="letra[]" value="<?php echo $letra; ?>" class="letra-chk" id="chk<?php echo $letra; ?>" <?php echo ($cnt === 0) ? 'disabled' : ''; ?>>
                    <label class="letra-label" for="chk<?php echo $letra; ?>" title="<?php echo $letra; ?>: <?php echo $cnt; ?> sitios" <?php echo ($cnt === 0) ? 'style="opacity:0.3;cursor:default;"' : ''; ?>><?php echo $letra; ?><sup style="font-size:0.6em;margin-left:1px;"><?php echo $cnt; ?></sup></label>
                </span>
            <?php endforeach; ?>
                <?php $cntNum = isset($conteoLetras['#']) ? $conteoLetras['#'] : 0; ?>
                <span>
                    <input type="checkbox" name="letra[]" value="#" class="letra-chk" id="chkNUM" <?php echo ($cntNum === 0) ? 'disabled' : ''; ?>>
                    <label class="letra-label" for="chkNUM" title="# Numeros: <?php echo $cntNum; ?> sitios" style="<?php echo ($cntNum === 0) ? 'opacity:0.3;cursor:default;' : ''; ?>background:<?php echo ($cntNum > 0) ? '#3a2a00' : '#2a2a4a'; ?>;">#<sup style="font-size:0.6em;margin-left:1px;"><?php echo $cntNum; ?></sup></label>
                </span>
            </div>

            <div class="letras-count" id="letrasCount">Seleccion: todos los subdominios</div>

            <script>
            function updateCount() {
                var checks = document.querySelectorAll('.letra-chk:checked');
                var el = document.getElementById('letrasCount');
                if (checks.length === 0) {
                    el.textContent = 'Seleccion: todos los subdominios (<?php echo $totalAllSites; ?>)';
                } else {
                    var total = 0;
                    checks.forEach(function(c) {
                        var sup = c.nextElementSibling.querySelector('sup');
                        total += parseInt(sup.textContent) || 0;
                    });
                    var letras = [];
                    checks.forEach(function(c) { letras.push(c.value); });
                    el.textContent = 'Seleccion: letras ' + letras.join(', ') + ' (' + total + ' subdominios)';
                }
            }
            document.querySelectorAll('.letra-chk').forEach(function(c) {
                c.addEventListener('change', updateCount);
            });
            </script>

            <div style="margin-top: 25px;">
                <?php if ($backupLimitExceeded): ?>
                <div class="warning-box" style="border-color:#d63031;background:#3d0000;text-align:left;">
                    <strong style="color:#ff6b6b;">LIMITE DE DISCO ALCANZADO</strong><br>
                    La carpeta respaldo/ ocupa <strong><?php echo formatBytes($currentBackupSize); ?></strong> (limite: <?php echo formatBytes(MAX_BACKUP_SIZE); ?>).<br>
                    Descargue los ZIPs y ejecute <strong>Limpiar respaldo/</strong> desde la pagina de Estado antes de continuar.
                </div>
                <button type="submit" class="btn btn-start" disabled style="opacity:0.4;cursor:not-allowed;">Iniciar Backup</button>
                <?php else: ?>
                <button type="submit" class="btn btn-start">Iniciar Backup</button>
                <?php endif; ?>
            </div>
        </form>
    </div>

    <div style="margin-top: 15px;">
        <a href="estado.php" class="btn btn-info">Ver Estado</a>
        <a href="copiar.php?reset=1" class="btn btn-warning" onclick="return confirm('Reiniciar progreso del backup?')">Reiniciar</a>
    </div>

<?php else: ?>

<?php
// ============================================================
// PROCESAR SUBDOMINIO ACTUAL
// ============================================================

// Mostrar modo activo
$modoLabel = $includeMedia ? 'CON MEDIA' : 'SIN MEDIA (solo archivos especificos)';
$modoClass = $includeMedia ? 'mode-tag-on' : 'mode-tag-off';
$letrasLabel = !empty($letrasActivas) ? implode(', ', $letrasActivas) : 'TODAS';
echo "<div style='margin: 10px 0;'>";
echo "Modo: <span class='mode-tag {$modoClass}'>{$modoLabel}</span>";
echo " <span class='mode-tag " . (!empty($letrasActivas) ? 'mode-tag-on' : 'mode-tag-off') . "'>Letras: {$letrasLabel}</span>";
echo " <span style='color:#888;font-size:0.8em;'>({$totalSites} sitios x {$maxPhases} fases)</span>";
echo "</div>";

// Verificar limite de disco antes de continuar
if ($backupLimitExceeded && $i < $totalSites) {
    $autoRefresh = false; // Detener auto-refresh
    echo "<div class='warning-box' style='border-color:#d63031;background:#3d0000;'>";
    echo "<strong style='color:#ff6b6b;'>LIMITE DE DISCO ALCANZADO</strong><br>";
    echo "La carpeta respaldo/ ocupa <strong>" . formatBytes($currentBackupSize) . "</strong> (limite: " . formatBytes(MAX_BACKUP_SIZE) . ").<br>";
    echo "Descargue los ZIPs y ejecute <a href='descargar.php?limpiar=1' style='color:#ff6b6b;' onclick=\"return confirm('Borrar TODOS los ZIPs?')\">Limpiar respaldo/</a> antes de continuar.";
    echo "</div>";
}

if ($i < $totalSites && !$backupLimitExceeded) {
    $sitePath = $sites[$i];
    $siteName = basename($sitePath);

    // Verificar si ya fue completamente procesado
    $isFullyDone = in_array($sitePath, $progress['respaldados']);

    // Verificar si esta fase ya fue procesada
    $siteDetail = isset($progress['detalle'][$siteName]) ? $progress['detalle'][$siteName] : null;
    $phasesDone = $siteDetail ? ($siteDetail['phases_done'] ?? 0) : 0;
    $isPhaseAlreadyDone = ($phase < $phasesDone);

    if ($isFullyDone || $isPhaseAlreadyDone) {

        echo "<div class='site-current'>";
        echo "<span class='site-name'>#{$i} - {$siteName}</span>";
        echo " <span class='log-info'>Fase " . ($phase + 1) . "/$maxPhases ya procesada, saltando...</span>";
        echo "</div>";

    } else {
        $timeStart = microtime(true);

        // RESPALDAR el subdominio (fase actual)
        list($filesCopied, $bytesCopied, $copyErrors, $filesNotFound) = backupSite($sitePath, $includeMedia, $phase);
        $elapsed = round(microtime(true) - $timeStart, 2);

        // Separar errores de "no encontrado" vs errores de copia
        $realErrors = [];
        $notFoundList = [];
        foreach ($copyErrors as $err) {
            if (strpos($err, 'No encontrado:') === 0 || strpos($err, 'Directorio no encontrado:') === 0) {
                $notFoundList[] = $err;
            } else {
                $realErrors[] = $err;
            }
        }

        // Acumular detalle por fases
        if (!isset($progress['detalle'][$siteName])) {
            $progress['detalle'][$siteName] = [
                'archivos'       => 0,
                'no_encontrados' => 0,
                'bytes'          => 0,
                'errores_copia'  => 0,
                'tiempo'         => 0,
                'phases_done'    => 0,
            ];
        }
        $progress['detalle'][$siteName]['archivos']       += $filesCopied;
        $progress['detalle'][$siteName]['no_encontrados'] += $filesNotFound;
        $progress['detalle'][$siteName]['bytes']          += $bytesCopied;
        $progress['detalle'][$siteName]['errores_copia']  += count($realErrors);
        $progress['detalle'][$siteName]['tiempo']         += $elapsed;
        $progress['detalle'][$siteName]['phases_done']     = $phase + 1;

        // Acumular totales globales
        $progress['archivos_total_copiados'] += $filesCopied;
        $progress['archivos_no_encontrados'] += $filesNotFound;
        $progress['bytes_total_copiados']    += $bytesCopied;

        if (!empty($realErrors)) {
            $prevErr = isset($progress['errores'][$siteName]) ? $progress['errores'][$siteName] . ' | ' : '';
            $progress['errores'][$siteName] = $prevErr . "Fase " . ($phase + 1) . ": " . count($realErrors) . " errores";
        }

        // Marcar como respaldado solo cuando TODAS las fases estan completas
        if ($phase + 1 >= $maxPhases) {
            $progress['respaldados'][] = $sitePath;
        }

        saveProgress($progress);

        // Log
        $logMsg = "F" . ($phase + 1) . "/$maxPhases $siteName ($phaseLabel) | $filesCopied archivos (" . formatBytes($bytesCopied) . ")";
        if ($filesNotFound > 0) $logMsg .= " | $filesNotFound no encontrados";
        if (!empty($realErrors)) $logMsg .= " | " . count($realErrors) . " errores";
        $logMsg .= " | {$elapsed}s";
        writeLog($logMsg);

        // UI
        echo "<div class='site-current'>";
        echo "<span class='site-name'>#{$i} - {$siteName}</span>";
        echo " <span class='log-info' style='font-size:0.8em;'>Fase " . ($phase + 1) . "/$maxPhases: " . htmlspecialchars($phaseLabel) . "</span>";
        if ($filesCopied > 0) {
            echo " <span class='log-ok'>$filesCopied archivos</span>";
        } else {
            echo " <span class='log-skip'>0 archivos</span>";
        }
        echo " <span style='color:#888;'>(" . formatBytes($bytesCopied) . " en {$elapsed}s)</span>";
        if ($filesNotFound > 0) {
            echo " <span class='log-warn'>| $filesNotFound no encontrados</span>";
        }
        echo "</div>";

        // Mostrar archivos no encontrados (solo en fase 0 para no saturar)
        if ($phase === 0 && !empty($notFoundList)) {
            echo "<div class='log-box'>";
            foreach ($notFoundList as $nf) {
                echo "<div class='log-warn'>  " . htmlspecialchars($nf) . "</div>";
            }
            echo "</div>";
        }

        // Mostrar errores de copia
        if (!empty($realErrors)) {
            echo "<div class='log-box'>";
            foreach (array_slice($realErrors, 0, 5) as $err) {
                echo "<div class='log-err'>  " . htmlspecialchars($err) . "</div>";
            }
            if (count($realErrors) > 5) {
                echo "<div class='log-err'>  ... y " . (count($realErrors) - 5) . " mas</div>";
            }
            echo "</div>";
        }
    }
}

// ============================================================
// ESTADISTICAS GLOBALES
// ============================================================

$respaldadosCount = count($progress['respaldados']);
$erroresCount     = count($progress['errores']);
$processedTotal   = $respaldadosCount + $erroresCount;
$pctComplete      = $totalSites > 0 ? round(($processedTotal / $totalSites) * 100, 1) : 0;

?>

    <h2>Progreso Global</h2>
    <div class="progress-bar">
        <div class="progress-fill fill-ok" style="width: <?php echo $pctComplete; ?>%">
            <?php echo $pctComplete; ?>% (<?php echo $processedTotal; ?>/<?php echo $totalSites; ?>)
        </div>
    </div>

    <div class="stats">
        <div class="stat-box">
            <div class="stat-value val-blue"><?php echo $totalSites; ?></div>
            <div class="stat-label">Sitios encontrados</div>
        </div>
        <div class="stat-box">
            <div class="stat-value val-green"><?php echo $respaldadosCount; ?></div>
            <div class="stat-label">Respaldados</div>
        </div>
        <div class="stat-box">
            <div class="stat-value val-red"><?php echo $erroresCount; ?></div>
            <div class="stat-label">Con errores</div>
        </div>
        <div class="stat-box">
            <div class="stat-value val-orange"><?php echo number_format($progress['archivos_total_copiados']); ?></div>
            <div class="stat-label">Archivos en ZIPs</div>
        </div>
        <div class="stat-box">
            <div class="stat-value val-yellow"><?php echo number_format($progress['archivos_no_encontrados']); ?></div>
            <div class="stat-label">No encontrados</div>
        </div>
        <div class="stat-box">
            <div class="stat-value val-purple"><?php echo formatBytes($progress['bytes_total_copiados']); ?></div>
            <div class="stat-label">Total respaldado</div>
        </div>
    </div>

<?php if ($i >= $totalSites && $totalSites > 0): ?>
    <div class="complete">
        <h2>BACKUP COMPLETADO</h2>
        <p>Se procesaron <?php echo $totalSites; ?> subdominios</p>
        <p>Respaldados: <?php echo $respaldadosCount; ?> | Con errores: <?php echo $erroresCount; ?></p>
        <p>Total: <?php echo number_format($progress['archivos_total_copiados']); ?> archivos (<?php echo formatBytes($progress['bytes_total_copiados']); ?>)</p>
        <?php if ($progress['archivos_no_encontrados'] > 0): ?>
        <p style="color: #ffd93d;">Archivos no encontrados: <?php echo number_format($progress['archivos_no_encontrados']); ?> (saltados)</p>
        <?php endif; ?>
    </div>
<?php endif; ?>

<?php if ($erroresCount > 0): ?>
    <h2>Errores (<?php echo $erroresCount; ?>)</h2>
    <div class="log-box">
    <?php foreach ($progress['errores'] as $site => $err): ?>
        <div class="log-err"><?php echo htmlspecialchars($site); ?>: <?php echo htmlspecialchars($err); ?></div>
    <?php endforeach; ?>
    </div>
<?php endif; ?>

    <div style="margin-top: 15px;">
        <a href="estado.php" class="btn btn-info">Ver Estado</a>
        <a href="copiar.php?reset=1" class="btn btn-warning" onclick="return confirm('Reiniciar progreso del backup?')">Reiniciar</a>
        <?php if ($i < $totalSites): ?>
        <a href="copiar.php?i=<?php echo $i; ?>&phase=<?php echo $phase; ?>&media=<?php echo $mediaParam; ?>&letras=<?php echo $letrasUrlParam; ?>" class="btn btn-primary">Reanudar</a>
        <?php endif; ?>
    </div>

    <div class="warning-box" style="margin-top: 15px;">
        <strong>Auto-refresh:</strong>
        <?php if ($autoRefresh && $i < $totalSites): ?>
            Respaldando... siguiente sitio en 1 segundo.
            <a href="estado.php" style="color: #ffd93d;">Detener y ver estado</a>
        <?php else: ?>
            Proceso finalizado o pausado.
        <?php endif; ?>
    </div>

<?php endif; // showStartScreen ?>

</div>
</body>
</html>
