<?php
/**
 * Demo Oracle — filtres du rapport temps reel, et leur plafonnement.
 *
 * Le module complet valide ces parametres en tete de son _report_realtime.php,
 * qui sert a la fois la page et son point de donnees. Ici les deux sont
 * separes (cf. report.php), et la validation doit donc vivre dans un fichier
 * commun — sinon la page et les donnees pourraient diverger, et le
 * plafonnement ne tiendrait que d'un cote.
 *
 * C'est le point important : la demonstration ne se contente pas de griser
 * les boutons. `parse()` IGNORE ce qui depasse et retombe sur la valeur
 * autorisee. Une URL forgee a la main — ?window=90&dim=sql_id&state=all —
 * rend exactement la meme chose qu'un clic normal.
 *
 * Safe to include multiple times (guard sur class_exists).
 */
if (class_exists('DemoOracleRealtimeFilters')) return;

class DemoOracleRealtimeFilters
{
    /** Expressions SQL de regroupement, par dimension. */
    private const DIM_EXPR = [
        'wait_class' => "CASE WHEN ash.session_state='ON CPU' THEN 'CPU' ELSE NVL(ash.wait_class,'Other') END",
        'module'     => "NVL(ash.module,'(none)')",
        'inst_id'    => "TO_CHAR(ash.inst_id)",
    ];

    /**
     * Toutes les dimensions du module complet, avec leur clef de libelle et un
     * drapeau disant si la demonstration les sert. Celles qui manquent restent
     * affichees, desactivees : le visiteur voit ce qu'offre la version
     * complete.
     *
     * @return array<string, array{label: string, demo: bool}>
     */
    public static function dimensions(): array
    {
        $served = DEMO_ORACLE_RT_DIMENSIONS;
        $all = [
            'wait_class'    => 'demo_oracle.rt_dim_wait_class',
            'event'         => 'demo_oracle.rt_dim_event',
            'sql_id'        => 'demo_oracle.rt_dim_sql_id',
            'module'        => 'demo_oracle.rt_dim_module',
            'program'       => 'demo_oracle.rt_dim_program',
            'inst_id'       => 'demo_oracle.rt_dim_inst_id',
            'session_state' => 'demo_oracle.rt_dim_session_state',
        ];
        $out = [];
        foreach ($all as $key => $label) {
            $out[$key] = ['label' => $label, 'demo' => in_array($key, $served, true)];
        }
        return $out;
    }

    /** Les trois fenetres du module complet ; seule la premiere est servie. */
    public static function windows(): array
    {
        return [DEMO_ORACLE_RT_WINDOW_MINUTES, 60, 90];
    }

    /**
     * Lit $_GET et rend des valeurs deja plafonnees.
     *
     * @return array{window:int, dim:string, dimExpr:string, svcHash:int,
     *               state:string, svcWhere:string, stateWhere:string,
     *               xfDim:string, xfVal:string, xfWhere:string, xfBind:bool}
     */
    public static function parse(): array
    {
        // Fenetre : figee. Le module complet propose 30, 60 et 90 minutes.
        $window = DEMO_ORACLE_RT_WINDOW_MINUTES;

        // Dimension : les trois servies, sinon retour a la premiere.
        $dim = preg_replace('/[^a-z_]/', '', strtolower((string)($_GET['dim'] ?? '')));
        if (!in_array($dim, DEMO_ORACLE_RT_DIMENSIONS, true)) {
            $dim = DEMO_ORACLE_RT_DIMENSIONS[0];
        }

        // Service : « tous », toujours. 0 = pas de filtre.
        $svcHash  = 0;
        $svcWhere = '';

        // Etat : sessions actives, toujours.
        $state      = 'active';
        $stateWhere = "AND (ash.session_state = 'ON CPU'"
                    . " OR (ash.session_state = 'WAITING' AND ash.wait_class != 'Idle'))";

        /*
         * Filtre croise : conserve tel quel. Il ne donne acces a rien de plus
         * — il restreint ce que la fenetre courante montre deja — et c'est ce
         * qui rend le rapport temps reel interessant a demontrer.
         */
        $xfDim = preg_replace('/[^a-z_]/', '', strtolower((string)($_GET['xf_dim'] ?? '')));
        if (!in_array($xfDim, ['sql_id', 'event', 'module', 'action', 'machine', 'inst_id'], true)) {
            $xfDim = '';
        }
        $xfVal   = $xfDim !== '' ? (string)($_GET['xf_val'] ?? '') : '';
        $xfWhere = '';
        $xfBind  = false;

        if ($xfDim !== '' && $xfVal !== '') {
            [$xfWhere, $xfBind] = match ($xfDim) {
                'event'   => $xfVal === 'CPU'
                             ? ["AND ash.session_state = 'ON CPU'", false]
                             : ['AND ash.event = :xf_val', true],
                'sql_id'  => ['AND ash.sql_id = :xf_val', true],
                'module'  => ['AND ash.module = :xf_val', true],
                'action'  => ['AND ash.action = :xf_val', true],
                'machine' => ['AND ash.machine = :xf_val', true],
                'inst_id' => ['AND ash.inst_id = TO_NUMBER(:xf_val)', true],
                default   => ['', false],
            };
        }

        return [
            'window'     => $window,
            'dim'        => $dim,
            'dimExpr'    => self::DIM_EXPR[$dim],
            'svcHash'    => $svcHash,
            'state'      => $state,
            'svcWhere'   => $svcWhere,
            'stateWhere' => $stateWhere,
            'xfDim'      => $xfDim,
            'xfVal'      => $xfVal,
            'xfWhere'    => $xfWhere,
            'xfBind'     => $xfBind,
        ];
    }
}
