<?php
/**
 * Demo Oracle — memoire SGA et PGA (section « config/memory »).
 *
 * Portage de modules/oracle/_report_memory.php, sans retrait : ce rapport est
 * une lecture pure — V$SGAINFO, V$SGA_DYNAMIC_COMPONENTS, V$PGASTAT — et le
 * module complet n'y propose aucune action. La demonstration le sert donc a
 * l'identique.
 *
 * Inclus par report.php. Variables : $oraDb, $db, $currentUser, $settings.
 */

/** @var array      $oraDb       */
/** @var object     $db          */
/** @var array|null $currentUser */
/** @var object     $settings    */

require_once __DIR__ . '/lib/DemoOracleOciConnect.php';
require_once __DIR__ . '/lib/DemoOracleMemoryRepository.php';

/* ── Oracle data fetch ──────────────────────────────────────────────────────── */
$ociError   = null;
$fetchError = null;
$sgaInfo    = [];
$sgaDynamic = [];
$pgaStats   = [];

$conn = demo_oracle_oci_open($oraDb, $db, $ociError, '', 'config/memory');

if (!$conn) {
    $fetchError = $ociError
        ? ('ORA-' . $ociError['code'] . ': ' . $ociError['message'])
        : t('demo_oracle.connect_error');
} else {
    $sgaInfo    = DemoOracleMemoryRepository::fetchSgaInfo($conn);
    $sgaDynamic = DemoOracleMemoryRepository::fetchSgaDynamicComponents($conn);
    $pgaStats   = DemoOracleMemoryRepository::fetchPgaStats($conn);
    oci_close($conn);
}

/* ── SGA summary ────────────────────────────────────────────────────────────── */
// Rows excluded from treemap: they are totals/meta, not allocations
$sgaMetaNames = ['Total SGA Size', 'Maximum SGA Size', 'Granule Size'];

$sgaTotalBytes  = 0;
$sgaFreeBytes   = 0;
$sgaBufferBytes = 0;
$sgaSharedBytes = 0;
$sgaTreemapRows = [];

foreach ($sgaInfo as $row) {
    if ($row['name'] === 'Total SGA Size')          { $sgaTotalBytes  = $row['bytes']; continue; }
    if ($row['name'] === 'Free SGA Memory Available'){ $sgaFreeBytes   = $row['bytes']; }
    if (stripos($row['name'], 'buffer cache') !== false) $sgaBufferBytes = max($sgaBufferBytes, $row['bytes']);
    if (stripos($row['name'], 'shared pool')  !== false) $sgaSharedBytes = max($sgaSharedBytes, $row['bytes']);
    if (in_array($row['name'], $sgaMetaNames)) continue;
    if ($row['bytes'] > 0) $sgaTreemapRows[] = $row;
}

/* ── PGA key values ─────────────────────────────────────────────────────────── */
$pgaTarget     = (int)($pgaStats['aggregate PGA target parameter']['value'] ?? 0);
$pgaAutoTarget = (int)($pgaStats['aggregate PGA auto target']['value']      ?? 0);
$pgaAllocated  = (int)($pgaStats['total PGA allocated']['value']            ?? 0);
$pgaInuse      = (int)($pgaStats['total PGA inuse']['value']                ?? 0);
$pgaFreeable   = (int)($pgaStats['total freeable PGA memory']['value']      ?? 0);
$pgaMaxAlloc   = (int)($pgaStats['maximum PGA allocated']['value']          ?? 0);
$pgaOverAlloc  = (int)($pgaStats['over allocation count']['value']          ?? 0);
$cacheHitRaw   = (float)($pgaStats['cache hit percentage']['value']         ?? 0);
$cacheHitPct   = round($cacheHitRaw / 100, 1); // stored as hundredths of %
$processCount  = (int)($pgaStats['process count']['value']                  ?? 0);
$maxProcesses  = (int)($pgaStats['max processes ever allocated']['value']   ?? 0);
$bytesProc     = (int)($pgaStats['bytes processed']['value']                ?? 0);
$extraBytes    = (int)($pgaStats['extra bytes read/written']['value']       ?? 0);
$pgaForAuto    = (int)($pgaStats['total PGA used for auto workareas']['value']   ?? 0);
$pgaForManual  = (int)($pgaStats['total PGA used for manual workareas']['value'] ?? 0);

// Cache hit color (>= 95% = good, >= 80% = warning, < 80% = bad)
$cacheHitClass = $cacheHitPct >= 95 ? 'text-success'
               : ($cacheHitPct >= 80 ? 'text-warning' : 'text-danger');

/* ── JSON for JS charts ────────────────────────────────────────────────────── */
$sgaTreemapJson = json_encode(array_values($sgaTreemapRows));

$pgaChartLabels = [
    'target'    => t('demo_oracle.mem_pga_target'),
    'max'       => t('demo_oracle.mem_pga_max'),
    'allocated' => t('demo_oracle.mem_pga_allocated'),
    'inuse'     => t('demo_oracle.mem_pga_inuse'),
    'freeable'  => t('demo_oracle.mem_pga_freeable'),
];

$pgaChartValues = [
    'target'    => $pgaTarget,
    'allocated' => $pgaAllocated,
    'inuse'     => $pgaInuse,
    'maxAlloc'  => $pgaMaxAlloc,
    'freeable'  => $pgaFreeable,
];

/* ── Helpers ────────────────────────────────────────────────────────────────── */
if (!function_exists('_demo_mem_fmtBytes')) {
function _demo_mem_fmtBytes(int $b): string {
    if ($b <= 0)          return '0 B';
    if ($b >= 1073741824) return round($b / 1073741824, 2) . ' GB';
    if ($b >= 1048576)    return round($b / 1048576, 1) . ' MB';
    if ($b >= 1024)       return round($b / 1024, 1) . ' KB';
    return $b . ' B';
}
}

/* ── Render view ─────────────────────────────────────────────────────────────── */
View::display(__DIR__ . '/views/report/memory.php', [
    'settings'        => $settings,
    'fetchError'      => $fetchError,
    'sgaTotalBytes'   => $sgaTotalBytes,
    'sgaFreeBytes'    => $sgaFreeBytes,
    'sgaBufferBytes'  => $sgaBufferBytes,
    'sgaSharedBytes'  => $sgaSharedBytes,
    'sgaTreemapRows'  => $sgaTreemapRows,
    'sgaDynamic'      => $sgaDynamic,
    'pgaStats'        => $pgaStats,
    'pgaTarget'       => $pgaTarget,
    'pgaAutoTarget'   => $pgaAutoTarget,
    'pgaAllocated'    => $pgaAllocated,
    'pgaInuse'        => $pgaInuse,
    'pgaFreeable'     => $pgaFreeable,
    'pgaMaxAlloc'     => $pgaMaxAlloc,
    'pgaOverAlloc'    => $pgaOverAlloc,
    'cacheHitPct'     => $cacheHitPct,
    'cacheHitClass'   => $cacheHitClass,
    'processCount'    => $processCount,
    'maxProcesses'    => $maxProcesses,
    'bytesProc'       => $bytesProc,
    'extraBytes'      => $extraBytes,
    'pgaForAuto'      => $pgaForAuto,
    'pgaForManual'    => $pgaForManual,
    'sgaTreemapJson'  => $sgaTreemapJson,
    'pgaChartLabels'  => $pgaChartLabels,
    'pgaChartValues'  => $pgaChartValues,
]);
