<?php
/**
 * WebEngine CMS / Nexora realm-aware cache manager.
 */
if(!defined('access') || access !== 'admincp') die();
NexoraRbac::requirePermission('system.manage');

echo '<h1 class="page-header">Cache Manager</h1>';

if(!function_exists('nexoraAdminRunCronCacheJob')) {
    function nexoraAdminRunCronCacheJob($filePath) { include($filePath); }
}

try {
    $cacheManager = new CacheManager();
    $realm = class_exists('NexoraRealm') && NexoraRealm::enabled() ? NexoraRealm::active() : null;
    $realmLabel = $realm !== null ? NexoraRealm::label($realm) : 'Default';

    if(isset($_POST['action'])) {
        try {
            switch($_POST['action']) {
                case 'clear':
                    $cacheManager->setFile($_POST['file']);
                    $cacheManager->clearCacheData();
                    message('success', 'Caché limpiada. El cron volverá a poblarla.');
                    break;
                case 'rebuildrealm':
                    $scaffold = $cacheManager->recoverRealmCacheScaffold($realm);
                    if(count($scaffold['errors']) > 0) {
                        throw new Exception('No se pudieron preparar algunos archivos: '.implode(', ', $scaffold['errors']));
                    }
                    if(!defined('NEXORA_CRON_REALM_RUNNER')) define('NEXORA_CRON_REALM_RUNNER', true);
                    if($realm !== null) NexoraRealm::selectPublic($realm, false);
                    $jobs = array(
                        'levels_ranking.php',
                        'resets_ranking.php',
                        'killers_ranking.php',
                        'masterlevel_ranking.php',
                        'guilds_ranking.php',
                        'grandresets_ranking.php',
                        'online_ranking.php',
                        'gens_ranking.php',
                        'votes_ranking.php',
                        'castle_siege.php',
                        'server_info.php',
                        'character_country.php',
                        'online_characters.php',
                        'event_rankings.php',
                    );
                    $executed = array();
                    $errors = array();
                    foreach($jobs as $job) {
                        $path = __PATH_CRON__.$job;
                        if(!is_file($path)) { $errors[] = $job.' (no existe)'; continue; }
                        try {
                            nexoraAdminRunCronCacheJob($path);
                            $executed[] = $job;
                        } catch(Throwable $jobEx) {
                            $errors[] = $job.': '.$jobEx->getMessage();
                            @error_log('[Nexora cache rebuild]['.$realmLabel.']['.$job.'] '.$jobEx->getMessage());
                        }
                    }
                    NexoraAudit::log('admin.cache_rebuild_realm', 'realm', $realmLabel, null, array('executed'=>$executed,'errors'=>$errors), $realm);
                    if(count($errors) > 0) {
                        message('warning', 'Reconstrucción parcial: '.count($executed).' tareas correctas y '.count($errors).' con error. Revisa php_errors.log.');
                    } else {
                        message('success', 'Caché de '.$realmLabel.' reconstruida correctamente ('.count($executed).' tareas).');
                    }
                    break;
                case 'deleteguildcache':
                    $cacheManager->deleteGuildCache();
                    message('success', 'Caché de perfiles de guild eliminada.');
                    break;
                case 'deleteplayercache':
                    $cacheManager->deletePlayerCache();
                    message('success', 'Caché de perfiles de personajes eliminada.');
                    break;
                default:
                    throw new Exception('The requested action is not valid.');
            }
        } catch(Exception $ex) {
            message('error', $ex->getMessage());
        }
    }

    // Opening this page also repairs a deleted realm cache directory/files without querying SQL.
    $scaffold = $cacheManager->recoverRealmCacheScaffold($realm);
    $health = $cacheManager->getRealmCacheHealth($realm);
    $missing = 0;
    $notWritable = 0;
    $latest = 0;
    foreach($health as $row) {
        if(!$row['exists']) $missing++;
        if(!$row['writable']) $notWritable++;
        if($row['mtime'] > $latest) $latest = $row['mtime'];
    }
    $healthOk = $missing === 0 && $notWritable === 0;
    ?>
    <div class="panel <?php echo $healthOk ? 'panel-success' : 'panel-warning'; ?>">
      <div class="panel-heading"><strong>Salud de caché · <?php echo htmlspecialchars($realmLabel, ENT_QUOTES, 'UTF-8'); ?></strong></div>
      <div class="panel-body">
        <div class="row">
          <div class="col-sm-3"><strong>Archivos esperados</strong><br><?php echo count($health); ?></div>
          <div class="col-sm-3"><strong>Faltantes</strong><br><?php echo (int)$missing; ?></div>
          <div class="col-sm-3"><strong>No escribibles</strong><br><?php echo (int)$notWritable; ?></div>
          <div class="col-sm-3"><strong>Último cambio</strong><br><?php echo $latest ? date('Y/m/d H:i:s', $latest) : 'Nunca'; ?></div>
        </div>
        <hr>
        <form method="post" action="<?php echo admincp_base('cachemanager'); ?>" onsubmit="return confirm('¿Reconstruir ahora la caché de <?php echo htmlspecialchars($realmLabel, ENT_QUOTES, 'UTF-8'); ?> desde SQL?');">
          <input type="hidden" name="action" value="rebuildrealm">
          <button type="submit" class="btn btn-primary">Reconstruir caché de <?php echo htmlspecialchars($realmLabel, ENT_QUOTES, 'UTF-8'); ?></button>
          <span class="text-muted" style="margin-left:8px">Crea archivos faltantes y ejecuta únicamente los productores de caché del reino.</span>
        </form>
      </div>
    </div>
    <?php

    $cacheFileList = $cacheManager->getCacheFileListAndData();
    if(!is_array($cacheFileList)) throw new Exception('No cache files found.');

    echo '<table class="table table-hover">';
        echo '<thead><tr><th>Cache File</th><th>Size</th><th>Last Modification</th><th>Writable</th><th>Actions</th></tr></thead>';
        echo '<tbody>';
        foreach($cacheFileList as $row) {
            echo '<tr>';
                echo '<td>'.htmlspecialchars($row['file'], ENT_QUOTES, 'UTF-8').'</td>';
                echo '<td>'.readableFileSize($row['size'], 2).'</td>';
                echo '<td>'.$row['edit'].'</td>';
                echo '<td>'.($row['write'] == 1 ? '<span class="label label-success">Yes</span>' : '<span class="label label-danger">Not Writable</span>').'</td>';
                echo '<td><form method="post" action="'.admincp_base('cachemanager').'" style="display:inline"><input type="hidden" name="action" value="clear"><input type="hidden" name="file" value="'.htmlspecialchars($row['file'], ENT_QUOTES, 'UTF-8').'"><button type="submit" class="btn btn-xs btn-danger">Clear Data</button></form></td>';
            echo '</tr>';
        }
        echo '</tbody>';
    echo '</table>';

    echo '<div class="row">';
        echo '<div class="col-xs-12 col-md-6 col-lg-6">';
            $guildProfilesCache = $cacheManager->getCacheFileListAndData('guild');
            $guildCacheTotalSize = 0;
            if(is_array($guildProfilesCache)) {
                $guildProfilesCacheCount = count($guildProfilesCache);
                foreach($guildProfilesCache as $guildCache) $guildCacheTotalSize += $guildCache['size'];
            } else $guildProfilesCacheCount = 0;
            echo '<h3>Guild Profiles Cache:</h3><table class="table table-hover"><tbody>';
            echo '<tr><th>Cache Files:</th><td>'.number_format($guildProfilesCacheCount).'</td></tr>';
            echo '<tr><th>Total Files Size:</th><td>'.readableFileSize($guildCacheTotalSize, 2).'</td></tr>';
            if($guildProfilesCacheCount > 0) echo '<tr><th></th><td><form method="post" action="'.admincp_base('cachemanager').'"><input type="hidden" name="action" value="deleteguildcache"><button type="submit" class="btn btn-xs btn-danger">Delete Guild Profiles Cache</button></form></td></tr>';
            echo '</tbody></table>';
        echo '</div>';
        echo '<div class="col-xs-12 col-md-6 col-lg-6">';
            $playerProfilesCache = $cacheManager->getCacheFileListAndData('player');
            $playerCacheTotalSize = 0;
            if(is_array($playerProfilesCache)) {
                $playerProfilesCacheCount = count($playerProfilesCache);
                foreach($playerProfilesCache as $playerCache) $playerCacheTotalSize += $playerCache['size'];
            } else $playerProfilesCacheCount = 0;
            echo '<h3>Player Profiles Cache:</h3><table class="table table-hover"><tbody>';
            echo '<tr><th>Cache Files:</th><td>'.number_format($playerProfilesCacheCount).'</td></tr>';
            echo '<tr><th>Total Files Size:</th><td>'.readableFileSize($playerCacheTotalSize, 2).'</td></tr>';
            if($playerProfilesCacheCount > 0) echo '<tr><th></th><td><form method="post" action="'.admincp_base('cachemanager').'"><input type="hidden" name="action" value="deleteplayercache"><button type="submit" class="btn btn-xs btn-danger">Delete Player Profiles Cache</button></form></td></tr>';
            echo '</tbody></table>';
        echo '</div>';
    echo '</div>';

} catch(Exception $ex) {
    message('error', $ex->getMessage());
}
