<?php
/**
 * Main plugin orchestrator (singleton).
 *
 * @package Brainwerk SEO Suite
 */

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

final class Seoforge {

    private static $instance = null;

    /** @var Seoforge_Loader */
    public $loader;

    public static function instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        $this->loader = new Seoforge_Loader();
        $this->set_locale();
        $this->load_modules();
    }

    private function set_locale() {
        // Load the plugin's *bundled* translations from /languages.
        //
        // WordPress 4.6+ auto-loads any community translations from
        // translate.wordpress.org (into the global wp-content/languages/plugins/
        // dir) and those correctly take precedence — but its just-in-time loader
        // scans ONLY that global dir, never a plugin's own /languages folder.
        // So without this explicit call the .mo files we ship (de_DE, de_AT,
        // es_ES, fr_FR) are never loaded: e.g. an Austrian `de_AT` site — which
        // has no community catalog on w.org — shows the whole plugin in English.
        // load_plugin_textdomain() registers our folder as a fallback; it is
        // fully wp.org-compliant (bundling translations is an accepted reason).
        $this->loader->add_action( 'init', $this, 'load_plugin_translations', 1 );

        // Also on `init`: the one-time DB-schema migration check.
        //
        // NOTE: this MUST run on a hook that fires *after* plugins_loaded — the
        // plugin itself bootstraps on plugins_loaded, so registering another
        // plugins_loaded callback here would be too late and never fire (which
        // silently broke schema auto-migration). `init` is the first safe hook.
        $this->loader->add_action( 'init', $this, 'maybe_migrate', 1 );
    }

    /**
     * Register the plugin's bundled translations.
     *
     * Runs on `init` (WordPress 6.7+ emits a _doing_it_wrong() notice when a
     * textdomain is loaded earlier). WordPress still prefers any newer catalog
     * in the global languages dir; this only adds our shipped .mo files as the
     * fallback source, which is the sole translation source for locales like
     * de_AT that have no entry on translate.wordpress.org.
     */
    public function load_plugin_translations() {
        load_plugin_textdomain(
            'brainwerk-seo-suite',
            false,
            dirname( SEOFORGE_BASENAME ) . '/languages'
        );
    }

    /**
     * Run the schema migration when a newer DB version ships.
     *
     * Gated to the admin context so a public front-end request can never
     * trigger DDL (dbDelta): a logged-in admin loading wp-admin after an
     * update performs the one-time migration. A short-lived network lock
     * prevents concurrent dbDelta runs from parallel admin requests.
     */
    public function maybe_migrate() {
        if ( ! is_admin() ) {
            return;
        }
        if ( (string) get_site_option( SEOFORGE_DB_VERSION_KEY ) === SEOFORGE_DB_VERSION ) {
            return;
        }
        if ( get_site_transient( 'seoforge_migrating' ) ) {
            return;
        }
        set_site_transient( 'seoforge_migrating', 1, 5 * MINUTE_IN_SECONDS );
        Seoforge_Activator::activate();
        delete_site_transient( 'seoforge_migrating' );
    }

    private function load_modules() {
        require_once SEOFORGE_PATH . 'includes/class-seoforge-utils.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-settings.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-crypto.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-compat.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-license.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-pro.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-tracker.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-sessions.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-aggregator.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-geo.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-stats.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-charts.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-health.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-meta.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-schema.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-sitemap.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-robots.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-llms.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-redirects.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-not-found.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-analyzer.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-notifications.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-onboarding.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-review-notice.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-tools.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-ai.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-ai-suggester.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-migrate.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-export.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-demo.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-rest.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-ajax.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-sanity.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-reports.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-intel.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-intel-client.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-bot-reputation.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-benchmark.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-audit.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-history.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-history-widgets.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-history-chain.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-log-reconciler.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-verify.php';
        require_once SEOFORGE_PATH . 'includes/class-seoforge-notary.php';
        if ( defined( 'WP_CLI' ) && WP_CLI ) {
            require_once SEOFORGE_PATH . 'includes/class-seoforge-cli.php';
        }

        Seoforge_License::register( $this->loader );
        Seoforge_Pro::register( $this->loader );
        Seoforge_Tracker::register( $this->loader );
        Seoforge_Sessions::register( $this->loader );
        Seoforge_Aggregator::register( $this->loader );
        Seoforge_Geo::register( $this->loader );
        Seoforge_Meta::register( $this->loader );
        Seoforge_Schema::register( $this->loader );
        Seoforge_Sitemap::register( $this->loader );
        Seoforge_Robots::register( $this->loader );
        Seoforge_Llms::register( $this->loader );
        Seoforge_Redirects::register( $this->loader );
        Seoforge_Not_Found::register( $this->loader );
        Seoforge_Analyzer::register( $this->loader );
        Seoforge_Notifications::register( $this->loader );
        Seoforge_Onboarding::register( $this->loader );
        Seoforge_Review_Notice::register( $this->loader );
        Seoforge_Tools::register( $this->loader );
        Seoforge_Migrate::register( $this->loader );
        Seoforge_Export::register( $this->loader );
        Seoforge_Rest::register( $this->loader );
        Seoforge_Ajax::register( $this->loader );
        Seoforge_Reports::register( $this->loader );
        Seoforge_Intel::register( $this->loader );
        Seoforge_Intel_Client::register( $this->loader );
        Seoforge_Audit::register( $this->loader );
        Seoforge_History::register( $this->loader );
        Seoforge_Verify::register( $this->loader );
        Seoforge_Notary::register( $this->loader );

        if ( is_admin() ) {
            require_once SEOFORGE_PATH . 'admin/class-seoforge-admin.php';
            require_once SEOFORGE_PATH . 'admin/class-seoforge-dashboard-widget.php';
            require_once SEOFORGE_PATH . 'admin/class-seoforge-post-meta-box.php';
            require_once SEOFORGE_PATH . 'admin/class-seoforge-admin-columns.php';
            Seoforge_Admin::register( $this->loader );
            Seoforge_Dashboard_Widget::register( $this->loader );
            Seoforge_Post_Meta_Box::register( $this->loader );
            Seoforge_Admin_Columns::register( $this->loader );
        }
    }

    public function run() {
        $this->loader->run();
    }
}
