<?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 = __DIR__;
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;
	use Volade_I18n;
	use Volade_Gamification;
	use Volade_Referral;
	use Volade_Discover;
	use Volade_Branding;
	use Volade_Premium;
	use Volade_Features;
	use Volade_Onboarding;
	use Volade_Activity;
	use Volade_Feedback;
	use 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 = 'core-version-switcher-by-volade';
		$locale = $this->resolve_sdk_locale( determine_locale() );
		$dir    = __DIR__ . '/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)', 'core-version-switcher-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', 'core-version-switcher-by-volade' )
			: __( 'Tableau de bord', 'core-version-switcher-by-volade' );

		add_menu_page(
			__( 'Volade', 'core-version-switcher-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', 'core-version-switcher-by-volade' ),
				__( 'Plugins', 'core-version-switcher-by-volade' ),
				$cap,
				self::get_plugins_hub_slug(),
				array( $this, 'render_plugins_hub' )
			);

			add_submenu_page(
				'volade',
				__( 'Vue d\'ensemble', 'core-version-switcher-by-volade' ),
				__( 'Vue d\'ensemble', 'core-version-switcher-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', 'core-version-switcher-by-volade' ),
				__( 'Connexion', 'core-version-switcher-by-volade' ),
				$cap,
				'volade-auth',
				array( $this, 'render_auth_page' )
			);
		} else {
			add_submenu_page(
				'volade',
				__( 'Découvrir', 'core-version-switcher-by-volade' ),
				__( 'Découvrir', 'core-version-switcher-by-volade' ),
				$cap,
				'volade-discover',
				array( $this, 'render_discover_page' )
			);
			add_submenu_page(
				'volade',
				__( 'Promouvoir', 'core-version-switcher-by-volade' ),
				__( 'Promouvoir', 'core-version-switcher-by-volade' ),
				$cap,
				'volade-promote',
				array( $this, 'render_promote_page' )
			);
			add_submenu_page(
				'volade',
				__( 'Parrainage', 'core-version-switcher-by-volade' ),
				__( 'Parrainage', 'core-version-switcher-by-volade' ),
				$cap,
				'volade-referrals',
				array( $this, 'render_referrals_page' )
			);
			add_submenu_page(
				'volade',
				__( 'V+ Premium', 'core-version-switcher-by-volade' ),
				__( 'V+ Premium', 'core-version-switcher-by-volade' ),
				$cap,
				'volade-premium',
				array( $this, 'render_premium_page' )
			);
			add_submenu_page(
				'volade',
				__( 'Activité', 'core-version-switcher-by-volade' ),
				__( 'Activité', 'core-version-switcher-by-volade' ),
				$cap,
				'volade-activity',
				array( $this, 'render_activity_page' )
			);
		}

		add_submenu_page(
			'volade',
			__( 'Réglages Volade', 'core-version-switcher-by-volade' ),
			__( 'Réglages', 'core-version-switcher-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', 'core-version-switcher-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 __DIR__ . '/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…', 'core-version-switcher-by-volade' ),
					'login_success'         => __( 'Connexion réussie. Redirection…', 'core-version-switcher-by-volade' ),
					'register_success'      => __( 'Compte créé. Redirection…', 'core-version-switcher-by-volade' ),
					'error_network'         => __( 'Erreur réseau. Réessayez.', 'core-version-switcher-by-volade' ),
					'error_unreachable'     => __( 'Impossible de contacter le serveur WordPress. Vérifiez que le site est en ligne.', 'core-version-switcher-by-volade' ),
					'error_server'          => __( 'Erreur serveur. Réactivez le plugin ou consultez les logs PHP.', 'core-version-switcher-by-volade' ),
					'error_session'         => __( 'Session expirée. Rechargez la page.', 'core-version-switcher-by-volade' ),
					'error_generic'         => __( 'Une erreur est survenue.', 'core-version-switcher-by-volade' ),
					'export_failed'         => __( 'Échec de l\'export.', 'core-version-switcher-by-volade' ),
					'processing'            => __( 'Traitement…', 'core-version-switcher-by-volade' ),
					'mission_done'          => __( 'Mission validée !', 'core-version-switcher-by-volade' ),
					'checkin_done'          => __( 'Aujourd\'hui validé — revenez demain !', 'core-version-switcher-by-volade' ),
					'checkin_cta'           => __( 'Valider aujourd\'hui (+10 XP)', 'core-version-switcher-by-volade' ),
					'mission_wait'          => __( 'Patientez quelques secondes…', 'core-version-switcher-by-volade' ),
					'mission_wait_progress' => __( 'Patientez…', 'core-version-switcher-by-volade' ),
					'mission_claim'         => __( 'Valider', 'core-version-switcher-by-volade' ),
					'guest_xp_hint'         => __( 'Connectez-vous pour cumuler l\'XP de cette mission.', 'core-version-switcher-by-volade' ),
					'guest_auth_required'   => __( 'Connectez-vous pour valider vos missions et cumuler l\'XP.', 'core-version-switcher-by-volade' ),
					'mission_validated'     => __( 'Validé', 'core-version-switcher-by-volade' ),
					'copied'                => __( 'Copié !', 'core-version-switcher-by-volade' ),
					/* translators: %d: number of plugins displayed in the discover grid. */
					'plugins_shown'         => __( '%d plugins shown', 'core-version-switcher-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 __DIR__ . '/views/admin-dashboard.php';
	}

	public function render_auth_page() {
		include __DIR__ . '/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 __DIR__ . '/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 __DIR__ . '/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 __DIR__ . '/views/admin-promote.php';
	}

	public function render_premium_page() {
		$user = $this->get_current_user();
		include __DIR__ . '/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 __DIR__ . '/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.', 'core-version-switcher-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.', 'core-version-switcher-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 __DIR__ . '/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', 'core-version-switcher-by-volade' ),
				'url'   => $this->volade_public_url( '/cgu' ),
				'desc'  => __( 'Règles d\'usage du compte et de l\'écosystème Volade.', 'core-version-switcher-by-volade' ),
			),
			array(
				'icon'  => '🛒',
				'label' => __( 'Conditions générales de vente', 'core-version-switcher-by-volade' ),
				'url'   => $this->volade_public_url( '/cgv' ),
				'desc'  => __( 'Abonnements V+, tarifs et modalités de facturation.', 'core-version-switcher-by-volade' ),
			),
			array(
				'icon'  => '🔒',
				'label' => __( 'Politique de confidentialité (RGPD)', 'core-version-switcher-by-volade' ),
				'url'   => $this->volade_public_url( '/confidentialite' ),
				'desc'  => __( 'Données collectées, durée de conservation et vos droits.', 'core-version-switcher-by-volade' ),
			),
			array(
				'icon'  => '⚖️',
				'label' => __( 'Mentions légales', 'core-version-switcher-by-volade' ),
				'url'   => $this->volade_public_url( '/mentions-legales' ),
				'desc'  => __( 'Éditeur du service, hébergeur et contact.', 'core-version-switcher-by-volade' ),
			),
			array(
				'icon'  => '🍪',
				'label' => __( 'Politique de cookies', 'core-version-switcher-by-volade' ),
				'url'   => $this->volade_public_url( '/cookies' ),
				'desc'  => __( 'Traceurs utilisés sur volade.com et vos choix.', 'core-version-switcher-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 __DIR__ . '/';
	}

	/**
	 * 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, 'core-version-switcher-by-volade' );
	}

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