<?php
/**
 * Demo Oracle — schema SQLite du module, cree et maintenu ici (idempotent).
 *
 * Difference notable avec le module Oracle complet : celui-ci fait creer ses
 * tables par le coeur (lib/Database.php). Le module de demonstration doit
 * pouvoir s'installer seul, dans son propre depot : il cree donc sa table
 * lui-meme, comme le font PostgresSchema et AuditOracleSchema.
 *
 * Une seule table, et c'est voulu. Le module complet en compte sept
 * (groupes, sous-groupes, acces, roles, permissions, grants, inclusions) pour
 * porter un modele de droits a trois niveaux. La demonstration n'a ni
 * regroupement par domaine ni distinction de role : qui accede au module voit
 * les bases declarees, en lecture seule.
 */
class DemoOracleSchema
{
    /** Cree la table si absente. Idempotent, joue en tete de chaque page. */
    public static function ensure(Database $db): void
    {
        /*
         * `host` et `service_name` ne sont plus NOT NULL : une base joignable
         * par portefeuille n'a ni l'un ni l'autre, elle a un alias TNS. La
         * contrainte est portee par le formulaire, selon le type de connexion.
         */
        $db->execute(
            "CREATE TABLE IF NOT EXISTS demo_oracle_databases (
                id           INTEGER PRIMARY KEY AUTOINCREMENT,
                name         TEXT NOT NULL,
                conn_type    TEXT NOT NULL DEFAULT 'standard',
                host         TEXT,
                port         INTEGER NOT NULL DEFAULT 1521,
                service_name TEXT,
                tns_alias    TEXT,
                wallet_path  TEXT,
                username     TEXT,
                password     TEXT,
                sysdba       INTEGER NOT NULL DEFAULT 0,
                description  TEXT,
                created_at   TEXT NOT NULL DEFAULT (datetime('now')),
                updated_at   TEXT NOT NULL DEFAULT (datetime('now'))
            )"
        );

        self::migrate($db);
    }

    /**
     * Ajoute les colonnes de la connexion par portefeuille aux installations
     * qui ont connu la version 1.0.0, ou la table ne les avait pas.
     *
     * `CREATE TABLE IF NOT EXISTS` ne touche pas une table existante : sans
     * cette passe, une mise a jour du module laisserait le schema en arriere et
     * la premiere requete citant conn_type echouerait.
     *
     * Le pattern est celui du coeur (cf. Database::migrate) : lire
     * PRAGMA table_info, ajouter ce qui manque. SQLite accepte ADD COLUMN,
     * il n'y a donc pas a recreer la table.
     */
    private static function migrate(Database $db): void
    {
        $have = [];
        foreach ($db->fetchAll("PRAGMA table_info(demo_oracle_databases)") as $col) {
            $have[$col['name']] = true;
        }

        $wanted = [
            'conn_type'   => "TEXT NOT NULL DEFAULT 'standard'",
            'tns_alias'   => 'TEXT',
            'wallet_path' => 'TEXT',
        ];
        foreach ($wanted as $name => $decl) {
            if (!isset($have[$name])) {
                $db->execute("ALTER TABLE demo_oracle_databases ADD COLUMN $name $decl");
            }
        }
    }

    /** Nombre de bases declarees. */
    public static function count(Database $db): int
    {
        return (int) $db->fetchScalar("SELECT COUNT(*) FROM demo_oracle_databases");
    }

    /**
     * Reste-t-il de la place ? La limite est le coeur de la demonstration :
     * elle est verifiee cote serveur, pas seulement masquee dans l'interface.
     */
    public static function hasRoom(Database $db): bool
    {
        return self::count($db) < DEMO_ORACLE_MAX_DATABASES;
    }
}
