<?php
/**
 * DatabaseInstaller — DB version-check and per-module schema upgrade runner.
 *
 * On admin requests it compares the stored DB version against
 * ULTRAGUARD_PRO_DB_VERSION and triggers schema updates when needed.
 *
 * MODULAR ARCHITECTURE CHANGE
 *   Instead of a single monolithic Database::create_tables() call, the installer
 *   now iterates over every ModuleSchemaInterface registered with the
 *   DatabaseTablesModule and calls $schema->install() on each one.
 *   This means adding a new module automatically gets its tables created
 *   without touching this file.
 *
 * @package UltraguardPro\core
 */

namespace UltraguardPro\core;

use UltraguardPro\Plugin;

if ( ! defined( 'ABSPATH' ) ) { exit; }

class DatabaseInstaller {

    private Plugin $plugin;

    public function __construct( Plugin $plugin ) {
        $this->plugin = $plugin;
        if ( is_admin() ) {
            add_action( 'admin_init', [ $this, 'maybe_upgrade' ], 5 );
        }
    }

    public function maybe_upgrade(): void {
        // Use a 5-minute transient to avoid fetching and comparing the DB version
        // on every admin page load.  The transient is deleted by run_upgrade() so
        // the next request after an upgrade always gets a fresh comparison.
        $cache_key = 'ultraguard_db_version_ok';
        if ( get_transient( $cache_key ) === ULTRAGUARD_PRO_DB_VERSION ) {
            return; // Already confirmed up-to-date in this window.
        }

        $installed = get_option( 'ultraguard_pro_db_version', '0' );
        if ( version_compare( $installed, ULTRAGUARD_PRO_DB_VERSION, '<' ) ) {
            delete_transient( $cache_key ); // Ensure we don't skip a real upgrade.
            $this->run_upgrade( $installed );
        } else {
            // DB is current — cache the result for 5 minutes.
            set_transient( $cache_key, ULTRAGUARD_PRO_DB_VERSION, 5 * MINUTE_IN_SECONDS );
        }
    }

    public function run_upgrade( string $from_version ): void {
        if ( ! function_exists( 'dbDelta' ) ) {
            require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        }

        // Install/upgrade every module schema that has been registered.
        // All modules boot during plugins_loaded / init:10, so by the time
        // admin_init fires every schema is registered.
        $db_tables_module = $this->plugin->modules->get_db_tables();
        if ( $db_tables_module ) {
            foreach ( $db_tables_module->get_registered_schemas() as $schema ) {
                try {
                    $schema->install();
                } catch ( \Throwable $e ) {
                    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
                        \UltraguardPro\core\Logger::error(
                            'Schema install failed for module [' . $schema->get_module_id() . ']: ' . $e->getMessage()
                        );
                    }
                }
            }
        }

        // Flush the schema name/column cache so the new tables are discoverable.
        DatabaseSchema::flush_cache();

        update_option( 'ultraguard_pro_db_version', ULTRAGUARD_PRO_DB_VERSION );
        delete_transient( 'ultraguard_db_version_ok' ); // Let next request re-validate.

        do_action( 'ultraguard_pro/db_upgraded', $from_version, ULTRAGUARD_PRO_DB_VERSION );
    }

    /**
     * Force-reinstall all schemas (used during activation).
     */
    public function install_all(): void {
        $this->run_upgrade( '0' );
    }
}
