<?php
/**
 * Volade SDK — Moteur principal
 * 
 * Chaque plugin Volade embarque ce SDK.
 * Usage : require_once __DIR__ . '/volade-sdk/boot.php';
 *         volade_sdk_boot( array(
 *             'plugin_file' => __FILE__,
 *             'plugin_slug' => 'mon-plugin',
 *             'plugin_name' => 'Mon Plugin',
 *             'sdk_path'    => __DIR__ . '/volade-sdk/class-volade-sdk.php',
 *         ) );
 *         add_action( 'volade_register_plugins', function () {
 *             Volade_SDK::get_instance()->register_plugin_submenu( ... );
 *         } );
 * 
 * @package Volade\SDK
 * @license GPL-2.0-or-later
 * @version 1.1.0
 */

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'Volade_SDK', false ) ) {
	return;
}

$volade_sdk_dir = dirname( __FILE__ );
require_once $volade_sdk_dir . '/class-volade-api.php';
require_once $volade_sdk_dir . '/trait-volade-auth.php';
require_once $volade_sdk_dir . '/trait-volade-i18n.php';
require_once $volade_sdk_dir . '/trait-volade-gamification.php';
require_once $volade_sdk_dir . '/trait-volade-referral.php';
require_once $volade_sdk_dir . '/trait-volade-discover.php';
require_once $volade_sdk_dir . '/trait-volade-branding.php';
require_once $volade_sdk_dir . '/trait-volade-premium.php';
require_once $volade_sdk_dir . '/trait-volade-features.php';
require_once $volade_sdk_dir . '/trait-volade-onboarding.php';
require_once $volade_sdk_dir . '/trait-volade-activity.php';
require_once $volade_sdk_dir . '/trait-volade-feedback.php';
require_once $volade_sdk_dir . '/trait-volade-promote.php';

final class Volade_SDK {
    use Volade_Auth, Volade_I18n, Volade_Gamification, Volade_Referral, Volade_Discover, Volade_Branding, Volade_Premium, Volade_Features, Volade_Onboarding, Volade_Activity, Volade_Feedback, Volade_Promote;

    private static $instance = null;
    /** @var array<string, array{slug:string,name:string,file:string}> */
    private $plugins = array();
    /** @var array<string, array{page_title:string,menu_title:string,callback:callable,capability:string}> */
    private static $plugin_submenus = array();
    private $plugin_file;
    private $plugin_slug;
    private $plugin_name;
    private $db_version = '1.3.0';
    private const CRON_COUNTER_OPTION = 'volade_sdk_active_count';

    public function __construct( $args = array() ) {
        if ( self::$instance ) {
            self::$instance->attach_host_plugin( $args );
            return;
        }

        self::$instance = $this;
        $this->init_sdk();
        $this->attach_host_plugin( $args );
    }

    /**
     * Démarre ou rattache un plugin hôte au SDK unique (un seul menu Volade).
     *
     * @param array{plugin_file?:string,plugin_slug?:string,plugin_name?:string} $args
     * @return self|null
     */
    public static function boot( array $args = array() ) {
        if ( self::$instance ) {
            self::$instance->attach_host_plugin( $args );
            return self::$instance;
        }

        return new self( $args );
    }

    public static function get_instance() {
        return self::$instance;
    }

    /**
     * @param array{plugin_file?:string,plugin_slug?:string,plugin_name?:string} $args
     */
    private function attach_host_plugin( array $args ) {
        $file = $args['plugin_file'] ?? '';
        $slug = $args['plugin_slug'] ?? '';
        $name = $args['plugin_name'] ?? '';

        if ( ! $this->plugin_file && $file ) {
            $this->plugin_file = $file;
            $this->plugin_slug = $slug;
            $this->plugin_name = $name;
        }

        if ( $slug ) {
            $this->plugins[ $slug ] = array(
                'slug' => $slug,
                'name' => $name,
                'file' => $file,
            );
        }

        if ( $file ) {
            register_activation_hook( $file, array( $this, 'on_activation' ) );
            register_deactivation_hook( $file, array( $this, 'on_deactivation' ) );
        }
    }

    private function init_sdk() {
        $this->init_hooks();
        add_action( 'plugins_loaded', array( $this, 'maybe_install_db' ), 1 );
        add_action( 'admin_init', array( $this, 'maybe_install_db' ), 0 );
    }

    private function init_hooks() {
        if ( $this->plugin_file ) {
            register_activation_hook( $this->plugin_file, array( $this, 'on_activation' ) );
            register_deactivation_hook( $this->plugin_file, array( $this, 'on_deactivation' ) );
        }
        add_action( 'init', array( $this, 'load_textdomain' ), 0 );
        add_action( 'init', array( $this, 'init_auth' ) );
        add_action( 'init', array( $this, 'init_gamification' ) );
        add_action( 'init', array( $this, 'init_referral' ) );
        add_action( 'init', array( $this, 'init_discover' ) );
        add_action( 'init', array( $this, 'init_branding' ) );
        add_action( 'init', array( $this, 'init_premium' ) );
        add_action( 'init', array( $this, 'init_features' ) );
        add_action( 'init', array( $this, 'init_onboarding' ) );
        add_action( 'init', array( $this, 'init_activity' ) );
        add_action( 'init', array( $this, 'init_feedback' ) );
        add_action( 'init', array( $this, 'init_promote' ) );
        add_action( 'admin_menu', array( $this, 'collect_plugin_registrations' ), 5 );
        add_action( 'admin_menu', array( $this, 'add_admin_menu' ), 20 );
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_menu_assets' ) );
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
        add_action( 'admin_footer', array( $this, 'render_branding_badge' ) );
        add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
        add_action( 'admin_init', array( $this, 'redirect_legacy_profile' ) );
        add_action( 'admin_init', array( $this, 'guard_member_ecosystem_pages' ), 1 );
        add_action( 'admin_init', array( $this, 'maybe_track_plugin_active' ) );
        add_filter( 'cron_schedules', array( $this, 'add_cron_schedule' ) );
    }

    /**
     * Normalise la locale WordPress vers un fichier de traduction SDK connu.
     * Par défaut : anglais (en_US), standard WordPress.org.
     *
     * @param string $locale Locale WordPress.
     * @return string
     */
    private function resolve_sdk_locale( $locale ) {
        $locale = (string) $locale;
        if ( 0 === strpos( $locale, 'fr' ) ) {
            return 'fr_FR';
        }
        if ( 0 === strpos( $locale, 'es' ) ) {
            return 'es_ES';
        }
        if ( 0 === strpos( $locale, 'de' ) ) {
            return 'de_DE';
        }
        if ( 0 === strpos( $locale, 'pt' ) ) {
            return 'pt_BR';
        }
        if ( 0 === strpos( $locale, 'it' ) ) {
            return 'it_IT';
        }
        return 'en_US';
    }

    public function load_textdomain() {
        $domain = 'php-compatibility-checker-by-volade';
        $locale = $this->resolve_sdk_locale( determine_locale() );
        $dir    = dirname( __FILE__ ) . '/languages';

        $php_file = $dir . '/' . $domain . '-' . $locale . '.l10n.php';
        if ( file_exists( $php_file ) ) {
            load_textdomain( $domain, $php_file );
            return;
        }

        $fallback = $dir . '/' . $domain . '-en_US.l10n.php';
        if ( file_exists( $fallback ) ) {
            load_textdomain( $domain, $fallback );
        }
    }

    public function on_activation() {
        $this->run_activation_tasks();
    }

    public function run_activation_tasks() {
        $this->maybe_install_db();
        $count = (int) get_option( self::CRON_COUNTER_OPTION, 0 ) + 1;
        update_option( self::CRON_COUNTER_OPTION, $count );
        if ( $count === 1 && ! wp_next_scheduled( 'volade_daily_cron' ) ) {
            wp_schedule_event( time(), 'volade_daily', 'volade_daily_cron' );
        }
    }

    public function on_deactivation() {
        $count = max( 0, (int) get_option( self::CRON_COUNTER_OPTION, 1 ) - 1 );
        update_option( self::CRON_COUNTER_OPTION, $count );
        if ( $count > 0 ) {
            return;
        }
        $timestamp = wp_next_scheduled( 'volade_daily_cron' );
        if ( $timestamp ) {
            wp_unschedule_event( $timestamp, 'volade_daily_cron' );
        }
    }

    /**
     * Catalogue, missions, parrainage, premium, activité — réservés aux comptes Volade connectés.
     */
    public function can_use_ecosystem_features() {
        return $this->is_user_logged_in();
    }

    /**
     * Redirige les visiteurs sans compte Volade hors des pages écosystème (accès URL direct).
     */
    public function guard_member_ecosystem_pages() {
        if ( ! is_admin() || ! isset( $_GET['page'] ) ) {
            return;
        }

        $page = sanitize_key( wp_unslash( $_GET['page'] ) );
        $member_pages = array(
            'volade-discover',
            'volade-promote',
            'volade-referrals',
            'volade-premium',
            'volade-activity',
        );

        if ( ! in_array( $page, $member_pages, true ) || $this->can_use_ecosystem_features() ) {
            return;
        }

        wp_safe_redirect( admin_url( 'admin.php?page=volade-auth' ) );
        exit;
    }

    public function maybe_track_plugin_active() {
        if ( ! is_admin() || ! $this->is_user_logged_in() ) {
            return;
        }
        $user = $this->get_current_user();
        if ( ! $user ) {
            return;
        }
        $throttle = 'volade_track_' . (int) $user['id'] . '_' . gmdate( 'Ymd' );
        if ( get_transient( $throttle ) ) {
            return;
        }
        set_transient( $throttle, 1, DAY_IN_SECONDS );
        foreach ( $this->plugins as $slug => $plugin ) {
            $this->track_plugin_active( $user['id'], $slug );
        }
    }

    public function add_cron_schedule( $schedules ) {
        $schedules['volade_daily'] = array(
            'interval' => 86400,
            'display'  => __( 'Quotidien (Volade)', 'php-compatibility-checker-by-volade' ),
        );
        return $schedules;
    }

    public function maybe_install_db() {
        $installed = get_option( 'volade_sdk_db_version' );
        if ( $installed === $this->db_version ) {
            return;
        }
        $this->install_db();
        update_option( 'volade_sdk_db_version', $this->db_version );
    }

    private function install_db() {
        global $wpdb;
        $charset = $wpdb->get_charset_collate();

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_users (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            pseudo varchar(50) NOT NULL,
            email varchar(255) NOT NULL,
            password_hash varchar(255) NOT NULL,
            display_name varchar(100) DEFAULT '',
            supabase_uid varchar(255) DEFAULT '',
            xp bigint(20) DEFAULT 0,
            level int(11) DEFAULT 1,
            referral_code varchar(20) DEFAULT '',
            referred_by varchar(20) DEFAULT '',
            streak int(11) DEFAULT 0,
            last_activity datetime DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            updated_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            UNIQUE KEY pseudo (pseudo),
            UNIQUE KEY email (email),
            UNIQUE KEY referral_code (referral_code)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_tokens (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) NOT NULL,
            token varchar(255) NOT NULL,
            expires_at datetime NOT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY user_id (user_id)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_badges (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) NOT NULL,
            badge_key varchar(50) NOT NULL,
            earned_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            UNIQUE KEY unique_badge (user_id, badge_key),
            KEY user_id (user_id)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_referrals (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            referrer_id bigint(20) NOT NULL,
            referred_id bigint(20) DEFAULT NULL,
            referral_code varchar(20) NOT NULL,
            status varchar(20) DEFAULT 'clicked',
            ip_address varchar(45) DEFAULT '',
            clicked_at datetime DEFAULT CURRENT_TIMESTAMP,
            converted_at datetime DEFAULT NULL,
            PRIMARY KEY  (id),
            KEY referrer_id (referrer_id)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_events (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) DEFAULT NULL,
            event_type varchar(50) NOT NULL,
            event_data longtext,
            plugin_slug varchar(100) DEFAULT '',
            ip_address varchar(45) DEFAULT '',
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY user_id (user_id)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_subscriptions (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) NOT NULL,
            plan varchar(20) DEFAULT 'free',
            status varchar(20) DEFAULT 'active',
            stripe_subscription_id varchar(255) DEFAULT '',
            stripe_customer_id varchar(255) DEFAULT '',
            current_period_start datetime DEFAULT NULL,
            current_period_end datetime DEFAULT NULL,
            canceled_at datetime DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            UNIQUE KEY user_id (user_id)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_sites (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) NOT NULL,
            site_url varchar(255) NOT NULL,
            plugin_slug varchar(100) DEFAULT '',
            wp_version varchar(20) DEFAULT '',
            php_version varchar(20) DEFAULT '',
            is_active tinyint(1) DEFAULT 1,
            activated_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            UNIQUE KEY unique_user_site (user_id, site_url),
            KEY user_id (user_id)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_reviews (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) NOT NULL,
            plugin_slug varchar(100) NOT NULL,
            rating int(11) NOT NULL,
            content text,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            updated_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            UNIQUE KEY unique_user_review (user_id, plugin_slug),
            KEY user_id (user_id)
        ) $charset;"
        );

        dbDelta(
            "CREATE TABLE {$wpdb->prefix}volade_mission_completions (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) NOT NULL,
            mission_key varchar(50) NOT NULL,
            period_key varchar(20) NOT NULL DEFAULT 'once',
            xp_awarded int(11) DEFAULT 0,
            completed_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            UNIQUE KEY unique_mission_period (user_id, mission_key, period_key),
            KEY user_id (user_id)
        ) $charset;"
        );
    }

    public function add_admin_menu() {
        $is_logged = $this->is_user_logged_in();
        $cap       = 'manage_options';
        $home_label = $is_logged
            ? __( 'Mon compte', 'php-compatibility-checker-by-volade' )
            : __( 'Tableau de bord', 'php-compatibility-checker-by-volade' );

        add_menu_page(
            __( 'Volade', 'php-compatibility-checker-by-volade' ),
            'Volade',
            $cap,
            'volade',
            array( $this, 'render_admin_page' ),
            'dashicons-superhero',
            58
        );

        add_submenu_page(
            'volade',
            $home_label,
            $home_label,
            $cap,
            'volade',
            array( $this, 'render_admin_page' )
        );

        if ( ! empty( self::$plugin_submenus ) ) {
            add_submenu_page(
                'volade',
                __( 'Plugins Volade', 'php-compatibility-checker-by-volade' ),
                __( 'Plugins', 'php-compatibility-checker-by-volade' ),
                $cap,
                self::get_plugins_hub_slug(),
                array( $this, 'render_plugins_hub' )
            );

            add_submenu_page(
                'volade',
                __( 'Vue d\'ensemble', 'php-compatibility-checker-by-volade' ),
                __( 'Vue d\'ensemble', 'php-compatibility-checker-by-volade' ),
                $cap,
                self::get_plugins_overview_slug(),
                array( $this, 'render_plugins_hub' )
            );

            foreach ( self::$plugin_submenus as $slug => $item ) {
                add_submenu_page(
                    'volade',
                    $item['page_title'],
                    $item['menu_title'],
                    $item['capability'],
                    self::get_plugin_page_slug( $slug ),
                    $item['callback']
                );
            }
        }

        if ( ! $is_logged ) {
            add_submenu_page(
                'volade',
                __( 'Connexion / Inscription', 'php-compatibility-checker-by-volade' ),
                __( 'Connexion', 'php-compatibility-checker-by-volade' ),
                $cap,
                'volade-auth',
                array( $this, 'render_auth_page' )
            );
        } else {
            add_submenu_page(
                'volade',
                __( 'Découvrir', 'php-compatibility-checker-by-volade' ),
                __( 'Découvrir', 'php-compatibility-checker-by-volade' ),
                $cap,
                'volade-discover',
                array( $this, 'render_discover_page' )
            );
            add_submenu_page(
                'volade',
                __( 'Promouvoir', 'php-compatibility-checker-by-volade' ),
                __( 'Promouvoir', 'php-compatibility-checker-by-volade' ),
                $cap,
                'volade-promote',
                array( $this, 'render_promote_page' )
            );
            add_submenu_page(
                'volade',
                __( 'Parrainage', 'php-compatibility-checker-by-volade' ),
                __( 'Parrainage', 'php-compatibility-checker-by-volade' ),
                $cap,
                'volade-referrals',
                array( $this, 'render_referrals_page' )
            );
            add_submenu_page(
                'volade',
                __( 'V+ Premium', 'php-compatibility-checker-by-volade' ),
                __( 'V+ Premium', 'php-compatibility-checker-by-volade' ),
                $cap,
                'volade-premium',
                array( $this, 'render_premium_page' )
            );
            add_submenu_page(
                'volade',
                __( 'Activité', 'php-compatibility-checker-by-volade' ),
                __( 'Activité', 'php-compatibility-checker-by-volade' ),
                $cap,
                'volade-activity',
                array( $this, 'render_activity_page' )
            );
        }

        add_submenu_page(
            'volade',
            __( 'Réglages Volade', 'php-compatibility-checker-by-volade' ),
            __( 'Réglages', 'php-compatibility-checker-by-volade' ),
            'manage_options',
            'volade-settings',
            array( $this, 'render_settings_page' )
        );
    }

    /**
     * Ajoute une page plugin sous le menu Volade (un seul menu pour tout l'écosystème).
     *
     * @param string   $slug        Identifiant unique (ex. wp-heartbeat-manager).
     * @param string   $page_title  Titre de la page.
     * @param string   $menu_title  Libellé dans la sidebar.
     * @param callable $callback    Rendu de la page.
     * @param string   $capability  Capacité requise.
     */
    public function register_plugin_submenu( $slug, $page_title, $menu_title, $callback, $capability = 'manage_options' ) {
        $slug = sanitize_key( $slug );
        if ( '' === $slug || isset( self::$plugin_submenus[ $slug ] ) ) {
            return;
        }

        self::$plugin_submenus[ $slug ] = array(
            'page_title' => $page_title,
            'menu_title' => $menu_title,
            'callback'   => $callback,
            'capability' => $capability,
        );
    }

    /**
     * Plugins enregistrés (menu + pages réglages).
     *
     * @return array<string, array{page_title:string,menu_title:string,callback:callable,capability:string}>
     */
    public function get_registered_plugins() {
        return self::$plugin_submenus;
    }

    public static function get_plugin_page_slug( $plugin_slug ) {
        return 'volade-' . $plugin_slug;
    }

    public static function get_plugins_hub_slug() {
        return 'volade-plugins';
    }

    public static function get_plugins_overview_slug() {
        return 'volade-plugins-overview';
    }

    /**
     * Les plugins Volade enregistrent leurs pages ici (avant construction du menu @20).
     */
    public function collect_plugin_registrations() {
        do_action( 'volade_register_plugins' );
    }

    /**
     * Masque les plugins dans la liste verticale (flyout à droite).
     * Ne pas retirer du $submenu global : WordPress refuse l'accès direct à la page.
     */
    private function get_plugin_sidebar_hide_css() {
        if ( empty( self::$plugin_submenus ) ) {
            return '';
        }

        $base = '#adminmenu .toplevel_page_volade .wp-submenu > li > a[href*="page=';
        $css  = $base . esc_attr( self::get_plugins_overview_slug() ) . '"]{display:none!important;}';

        foreach ( array_keys( self::$plugin_submenus ) as $slug ) {
            $slug = preg_replace( '/[^a-z0-9\-_]/', '', $slug );
            $css .= $base . 'volade-' . esc_attr( $slug ) . '"]{display:none!important;}';
        }

        return $css;
    }

    /**
     * Flyout « Plugins » dans la barre latérale WP (toutes les pages admin).
     */
    public function enqueue_admin_menu_assets() {
        if ( empty( self::$plugin_submenus ) || ! current_user_can( 'manage_options' ) ) {
            return;
        }

        $version = '1.3.6';
        wp_enqueue_style( 'volade-sdk-admin-menu', $this->get_url() . 'assets/admin-menu.css', array(), $version );
        $hide_css = $this->get_plugin_sidebar_hide_css();
        if ( $hide_css ) {
            wp_add_inline_style( 'volade-sdk-admin-menu', $hide_css );
        }
        wp_enqueue_script( 'volade-sdk-admin-menu', $this->get_url() . 'assets/admin-menu.js', array(), $version, true );

        $plugins = array();
        foreach ( self::$plugin_submenus as $slug => $item ) {
            $plugins[] = array(
                'slug'  => $slug,
                'title' => $item['menu_title'],
                'url'   => admin_url( 'admin.php?page=' . self::get_plugin_page_slug( $slug ) ),
            );
        }

        usort(
            $plugins,
            static function ( $a, $b ) {
                return strcasecmp( $a['title'], $b['title'] );
            }
        );

        wp_localize_script(
            'volade-sdk-admin-menu',
            'voladeMenu',
            array(
                'hubSlug'      => self::get_plugins_hub_slug(),
                'overviewSlug' => self::get_plugins_overview_slug(),
                'hubUrl'       => admin_url( 'admin.php?page=' . self::get_plugins_hub_slug() ),
                'overviewUrl'  => admin_url( 'admin.php?page=' . self::get_plugins_overview_slug() ),
                'hubLabel'     => __( 'Vue d\'ensemble', 'php-compatibility-checker-by-volade' ),
                'plugins'      => $plugins,
            )
        );
    }

    public function render_plugins_hub() {
        $hub_plugins = $this->get_installed_plugins_hub();
        $hub_stats   = $this->get_hub_stats( $hub_plugins );
        $user        = $this->get_current_user();

        if ( $this->can_use_ecosystem_features() ) {
            $discover_stats  = $this->get_discover_stats();
            $hub_suggestions = $this->get_hub_suggestions( 4 );
            $catalog_total   = (int) $discover_stats['total'];
        } else {
            $discover_stats  = array(
                'total'     => 0,
                'live'      => 0,
                'planned'   => 0,
                'categories'=> 0,
                'installed' => count( $hub_plugins ),
            );
            $hub_suggestions = array();
            $catalog_total   = 0;
        }

        include dirname( __FILE__ ) . '/views/admin-plugins-hub.php';
    }

    public function enqueue_admin_assets( $hook ) {
        $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
        if ( strpos( $hook, 'volade' ) === false && strpos( $page, 'volade' ) !== 0 ) {
            return;
        }
        wp_enqueue_style( 'volade-sdk-admin', $this->get_url() . 'assets/admin.css', array(), '1.5.9' );
        wp_enqueue_script( 'volade-sdk-admin', $this->get_url() . 'assets/admin.js', array( 'jquery' ), '1.5.9', true );
        wp_localize_script( 'volade-sdk-admin', 'voladeSDK', array(
            'ajax_url'     => admin_url( 'admin-ajax.php' ),
            'rest_url'     => rest_url( 'volade/v1/' ),
            'nonce'        => wp_create_nonce( 'volade_nonce' ),
            'access_level' => $this->get_access_level(),
            'redirects'    => array(
                'after_login'    => admin_url( 'admin.php?page=volade' ),
                'after_register' => admin_url( 'admin.php?page=volade&volade_welcome=1' ),
                'auth'           => admin_url( 'admin.php?page=volade-auth' ),
                'discover'       => admin_url( 'admin.php?page=volade-discover' ),
            ),
            'i18n'         => array(
                'loading'          => __( 'Chargement…', 'php-compatibility-checker-by-volade' ),
                'login_success'    => __( 'Connexion réussie. Redirection…', 'php-compatibility-checker-by-volade' ),
                'register_success' => __( 'Compte créé. Redirection…', 'php-compatibility-checker-by-volade' ),
                'error_network'    => __( 'Erreur réseau. Réessayez.', 'php-compatibility-checker-by-volade' ),
                'error_server'     => __( 'Erreur serveur. Réactivez le plugin ou consultez les logs PHP.', 'php-compatibility-checker-by-volade' ),
                'error_session'    => __( 'Session expirée. Rechargez la page.', 'php-compatibility-checker-by-volade' ),
                'error_generic'    => __( 'Une erreur est survenue.', 'php-compatibility-checker-by-volade' ),
                'export_failed'    => __( 'Échec de l\'export.', 'php-compatibility-checker-by-volade' ),
                'processing'       => __( 'Traitement…', 'php-compatibility-checker-by-volade' ),
                'mission_done'     => __( 'Mission validée !', 'php-compatibility-checker-by-volade' ),
                'checkin_done'     => __( 'Aujourd\'hui validé — revenez demain !', 'php-compatibility-checker-by-volade' ),
                'checkin_cta'      => __( 'Valider aujourd\'hui (+10 XP)', 'php-compatibility-checker-by-volade' ),
                'mission_wait'     => __( 'Patientez quelques secondes…', 'php-compatibility-checker-by-volade' ),
                'mission_wait_progress' => __( 'Patientez…', 'php-compatibility-checker-by-volade' ),
                'mission_claim'    => __( 'Valider', 'php-compatibility-checker-by-volade' ),
                'guest_xp_hint'    => __( 'Connectez-vous pour cumuler l\'XP de cette mission.', 'php-compatibility-checker-by-volade' ),
                'guest_auth_required' => __( 'Connectez-vous pour valider vos missions et cumuler l\'XP.', 'php-compatibility-checker-by-volade' ),
                'mission_validated' => __( 'Validé', 'php-compatibility-checker-by-volade' ),
                'copied'           => __( 'Copié !', 'php-compatibility-checker-by-volade' ),
                /* translators: %d: number of plugins displayed in the discover grid. */
                'plugins_shown'    => __( '%d plugins shown', 'php-compatibility-checker-by-volade' ),
            ),
        ) );
    }

    public function register_rest_routes() {
        register_rest_route( 'volade/v1', '/auth/register', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'rest_register' ),
            'permission_callback' => '__return_true',
        ) );
        register_rest_route( 'volade/v1', '/auth/login', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'rest_login' ),
            'permission_callback' => '__return_true',
        ) );
        register_rest_route( 'volade/v1', '/auth/me', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'rest_me' ),
            'permission_callback' => array( $this, 'check_auth' ),
        ) );
        register_rest_route( 'volade/v1', '/gamification/xp', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'rest_add_xp' ),
            'permission_callback' => array( $this, 'check_auth' ),
        ) );
        register_rest_route( 'volade/v1', '/referral/link', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'rest_get_referral_link' ),
            'permission_callback' => array( $this, 'check_auth' ),
        ) );
        register_rest_route( 'volade/v1', '/discover/plugins', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'rest_get_discover_plugins' ),
            'permission_callback' => array( $this, 'check_auth' ),
        ) );
        register_rest_route( 'volade/v1', '/access/status', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'rest_access_status' ),
            'permission_callback' => '__return_true',
        ) );
        register_rest_route( 'volade/v1', '/premium/status', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'rest_premium_status' ),
            'permission_callback' => array( $this, 'check_auth' ),
        ) );
        register_rest_route( 'volade/v1', '/premium/checkout', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'rest_premium_checkout' ),
            'permission_callback' => array( $this, 'check_auth' ),
        ) );
        register_rest_route( 'volade/v1', '/sites/register', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'rest_register_site' ),
            'permission_callback' => array( $this, 'check_auth' ),
        ) );
    }

    public function check_auth() {
        return $this->is_user_logged_in();
    }

    public function render_admin_page() {
        $user = $this->get_current_user();
        include dirname( __FILE__ ) . '/views/admin-dashboard.php';
    }

    public function render_auth_page() {
        include dirname( __FILE__ ) . '/views/admin-auth.php';
    }

    public function redirect_legacy_profile() {
        if ( ! is_admin() || ! isset( $_GET['page'] ) ) {
            return;
        }
        if ( 'volade-profile' !== sanitize_key( wp_unslash( $_GET['page'] ) ) ) {
            return;
        }
        wp_safe_redirect( admin_url( 'admin.php?page=volade' ) );
        exit;
    }

    public function render_profile_page() {
        wp_safe_redirect( admin_url( 'admin.php?page=volade' ) );
        exit;
    }

    public function render_referrals_page() {
        $user = $this->get_current_user();
        include dirname( __FILE__ ) . '/views/admin-referrals.php';
    }

    public function render_discover_page() {
        $discover_stats     = $this->get_discover_stats();
        $discover_catalog   = $this->get_discover_catalog();
        $discover_featured  = $this->get_discover_featured( $discover_catalog );
        $discover_groups    = $this->group_discover_by_category( $discover_catalog );
        $discover_categories = array_keys( $discover_groups );
        include dirname( __FILE__ ) . '/views/admin-discover.php';
    }

    public function render_promote_page() {
        $user       = $this->get_current_user();
        $missions      = $this->get_missions_for_user( $user['id'] );
        $calendar      = $this->get_calendar_days( $user['id'], 28 );
        $today_checked = $this->is_mission_completed( $user['id'], 'daily_checkin', 'daily' );
        $completed_cnt = count( array_filter( $missions, static function ( $m ) {
            return ! empty( $m['completed'] );
        } ) );
        $total_xp      = array_sum( array_map( static function ( $m ) {
            return ! empty( $m['completed'] ) ? (int) $m['xp'] : 0;
        }, $missions ) );
        $guest_mode = false;
        include dirname( __FILE__ ) . '/views/admin-promote.php';
    }

    public function render_premium_page() {
        $user = $this->get_current_user();
        include dirname( __FILE__ ) . '/views/admin-premium.php';
    }

    public function render_activity_page() {
        $user            = $this->get_current_user();
        $events          = $user ? $this->get_user_events( $user['id'], 80 ) : array();
        $activity_stats  = $user ? $this->get_activity_stats( $user['id'] ) : array();
        $activity_groups = $this->group_activity_by_day( $events );
        include dirname( __FILE__ ) . '/views/admin-activity.php';
    }

    public function render_settings_page() {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_die( esc_html__( 'Vous n\'avez pas la permission d\'accéder à cette page.', 'php-compatibility-checker-by-volade' ) );
        }
        if ( isset( $_POST['volade_settings_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['volade_settings_nonce'] ) ), 'volade_settings' ) ) {
            update_option( 'volade_show_badge', isset( $_POST['volade_show_badge'] ) ? '1' : '0' );
            update_option( 'volade_show_guest_banner', isset( $_POST['volade_show_guest_banner'] ) ? '1' : '0' );
            update_option( 'volade_show_admin_footer', isset( $_POST['volade_show_admin_footer'] ) ? '1' : '0' );
            delete_option( 'volade_show_social_proof' );
            echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Réglages enregistrés.', 'php-compatibility-checker-by-volade' ) . '</p></div>';
        }

        $show_badge         = get_option( 'volade_show_badge', '0' );
        $show_guest_banner  = get_option( 'volade_show_guest_banner', '0' );
        $show_admin_footer  = get_option( 'volade_show_admin_footer', '0' );
        $legal_links        = $this->get_legal_links();

        include dirname( __FILE__ ) . '/views/admin-settings.php';
    }

    /**
     * URL publique volade.com avec préfixe de locale (fr|en).
     *
     * @param string $path Chemin sans domaine, ex. /cms/wordpress/extensions/foo.
     * @return string
     */
    public function volade_public_url( $path = '/' ) {
        $user_locale = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
        $loc         = ( 0 === strpos( (string) $user_locale, 'fr' ) ) ? 'fr' : 'en';
        $normalized  = '/' . ltrim( (string) $path, '/' );

        return 'https://volade.com/' . $loc . $normalized;
    }

    /**
     * URL publique du catalogue ou d'une fiche extension CMS WordPress.
     *
     * @param string $slug Slug extension (vide = catalogue).
     * @return string
     */
    public function volade_extension_catalog_url( $slug = '' ) {
        if ( function_exists( 'volade_extension_catalog_url' ) ) {
            return volade_extension_catalog_url( $slug );
        }

        $path = VOLADE_CMS_WP_EXTENSIONS . ( $slug ? '/' . rawurlencode( (string) $slug ) : '' );

        return $this->volade_public_url( $path );
    }

    /**
     * URL publique de la documentation d'une extension.
     *
     * @param string $slug Slug extension WordPress.
     * @return string
     */
    public function volade_extension_doc_url( $slug ) {
        return $this->volade_extension_catalog_url( $slug );
    }

    /**
     * Liens légaux Volade (site central).
     *
     * @return array<int, array{icon:string,label:string,url:string,desc:string}>
     */
    public function get_legal_links() {
        return array(
            array(
                'icon'  => '📜',
                'label' => __( 'Conditions générales d\'utilisation', 'php-compatibility-checker-by-volade' ),
                'url'   => $this->volade_public_url( '/cgu' ),
                'desc'  => __( 'Règles d\'usage du compte et de l\'écosystème Volade.', 'php-compatibility-checker-by-volade' ),
            ),
            array(
                'icon'  => '🛒',
                'label' => __( 'Conditions générales de vente', 'php-compatibility-checker-by-volade' ),
                'url'   => $this->volade_public_url( '/cgv' ),
                'desc'  => __( 'Abonnements V+, tarifs et modalités de facturation.', 'php-compatibility-checker-by-volade' ),
            ),
            array(
                'icon'  => '🔒',
                'label' => __( 'Politique de confidentialité (RGPD)', 'php-compatibility-checker-by-volade' ),
                'url'   => $this->volade_public_url( '/confidentialite' ),
                'desc'  => __( 'Données collectées, durée de conservation et vos droits.', 'php-compatibility-checker-by-volade' ),
            ),
            array(
                'icon'  => '⚖️',
                'label' => __( 'Mentions légales', 'php-compatibility-checker-by-volade' ),
                'url'   => $this->volade_public_url( '/mentions-legales' ),
                'desc'  => __( 'Éditeur du service, hébergeur et contact.', 'php-compatibility-checker-by-volade' ),
            ),
            array(
                'icon'  => '🍪',
                'label' => __( 'Politique de cookies', 'php-compatibility-checker-by-volade' ),
                'url'   => $this->volade_public_url( '/cookies' ),
                'desc'  => __( 'Traceurs utilisés sur volade.com et vos choix.', 'php-compatibility-checker-by-volade' ),
            ),
        );
    }

    public function rest_premium_status() {
        $user = $this->get_current_user();
        if ( ! $user ) {
            return new WP_REST_Response( array( 'error' => 'Not authenticated' ), 401 );
        }
        return new WP_REST_Response( array(
            'tier'       => $this->get_tier( $user['id'] ),
            'is_premium' => $this->is_premium( $user['id'] ),
            'site_limit' => $this->get_site_limit( $user['id'] ),
            'sites_used' => $this->get_active_sites_count( $user['id'] ),
        ), 200 );
    }

    public function rest_premium_checkout( $request ) {
        $user = $this->get_current_user();
        if ( ! $user ) {
            return new WP_REST_Response( array( 'error' => 'Not authenticated' ), 401 );
        }
        $params = $request->get_params();
        $tier   = sanitize_text_field( $params['tier'] ?? '' );
        $period = sanitize_text_field( $params['period'] ?? 'monthly' );
        $tiers  = $this->get_all_tiers();
        if ( ! isset( $tiers[ $tier ] ) || $tier === 'free' ) {
            return new WP_REST_Response( array( 'error' => 'Invalid tier' ), 400 );
        }
        $url    = $this->get_checkout_url( $tier, $period );
        if ( ! $url ) {
            return new WP_REST_Response( array( 'error' => 'Checkout unavailable' ), 503 );
        }
        return new WP_REST_Response( array( 'url' => $url ), 200 );
    }

    public function rest_register_site() {
        $user = $this->get_current_user();
        if ( ! $user ) {
            return new WP_REST_Response( array( 'error' => 'Not authenticated' ), 401 );
        }
        $result = $this->register_site( $user['id'] );
        if ( is_wp_error( $result ) ) {
            return new WP_REST_Response( array( 'error' => $result->get_error_message() ), 403 );
        }
        return new WP_REST_Response( array(
            'site_id'    => $result,
            'sites_used' => $this->get_active_sites_count( $user['id'] ),
            'site_limit' => $this->get_site_limit( $user['id'] ),
        ), 201 );
    }

    public function get_plugin_name() {
        return $this->plugin_name;
    }

    public function get_plugin_slug() {
        return $this->plugin_slug;
    }

    public function get_plugins() {
        return $this->plugins;
    }

    /**
     * Instance SDK liée à un plugin (auth / features / premium partagés).
     */
    public static function for_plugin( $slug ) {
        return self::get_instance();
    }

    public function get_url() {
        foreach ( $this->plugins as $meta ) {
            if ( ! empty( $meta['file'] ) && is_readable( dirname( $meta['file'] ) . '/volade-sdk/class-volade-sdk.php' ) ) {
                return trailingslashit( plugin_dir_url( $meta['file'] ) ) . 'volade-sdk/';
            }
        }
        if ( $this->plugin_file ) {
            return trailingslashit( plugin_dir_url( $this->plugin_file ) ) . 'volade-sdk/';
        }
        return trailingslashit( plugin_dir_url( __FILE__ ) );
    }

    public function get_dir() {
        return dirname( __FILE__ ) . '/';
    }

    /**
     * Translate a string literal passed from SDK admin views.
     *
     * @param string $text Message text (always a literal at call sites).
     */
    public function __( $text ) {
        // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText -- View helper; callers pass string literals only.
        return __( $text, 'php-compatibility-checker-by-volade' );
    }

    public function _e( $text ) {
        echo esc_html( $this->__( $text ) );
    }
}
