<?php
/**
 * Sécurité des routes cockpit premium / agence (template_redirect).
 *
 * @package Avision
 */

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

/**
 * Chemin HTTP seul (sans query string). Évite les faux positifs si l’URL contient /premium-dashboard dans redirect_to sur /login/.
 *
 * @return string
 */
function avision_route_guard_get_request_path() {
	if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
		return '';
	}
	$uri = function_exists( 'wp_unslash' ) ? wp_unslash( (string) $_SERVER['REQUEST_URI'] ) : (string) $_SERVER['REQUEST_URI'];
	$path = function_exists( 'wp_parse_url' )
		? wp_parse_url( $uri, PHP_URL_PATH )
		: parse_url( $uri, PHP_URL_PATH );
	return is_string( $path ) ? $path : '';
}

/**
 * Accès cockpit sans redirection login : manage_options, super-admin, ou rôle administrator (filet si capa modifiée).
 *
 * @return bool
 */
function avision_route_guard_is_privileged_wp_user() {
	if ( ! function_exists( 'is_user_logged_in' ) || ! is_user_logged_in() ) {
		return false;
	}
	if ( function_exists( 'current_user_can' ) && current_user_can( 'manage_options' ) ) {
		return true;
	}
	if ( function_exists( 'is_super_admin' ) && is_super_admin() ) {
		return true;
	}
	$u = function_exists( 'wp_get_current_user' ) ? wp_get_current_user() : null;
	return $u && $u->exists() && in_array( 'administrator', (array) $u->roles, true );
}

/**
 * Administration WordPress et comptes avec manage_options : aucune redirection « videur » vers /login ou /connexion.
 *
 * @return bool True = ne pas appliquer la garde cockpit sur cette requête.
 */
function avision_route_guard_bypass_administration_context() {
	if ( function_exists( 'is_admin' ) && is_admin() ) {
		return true;
	}
	if ( isset( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] === 'wp-login.php' ) {
		return true;
	}
	$uri = isset( $_SERVER['REQUEST_URI'] )
		? (string) ( function_exists( 'wp_unslash' ) ? wp_unslash( (string) $_SERVER['REQUEST_URI'] ) : (string) $_SERVER['REQUEST_URI'] )
		: '';
	if ( $uri !== '' && stripos( $uri, 'wp-admin' ) !== false ) {
		return true;
	}
	// Filet : pages d’admin du plugin (AVI Control Center, CRON, tables cœur) — aucune redirection vers /premium-dashboard.
	$admin_like = ( $uri !== '' && ( stripos( $uri, 'admin.php' ) !== false || stripos( $uri, 'wp-admin' ) !== false ) );
	if ( $admin_like && ! empty( $_GET['page'] ) && is_string( $_GET['page'] ) && function_exists( 'sanitize_key' ) ) {
		$page = sanitize_key( function_exists( 'wp_unslash' ) ? wp_unslash( $_GET['page'] ) : $_GET['page'] );
		$avision_plugin_admin_slugs = array(
			'avision-dashboard',
			'avi-pages-admin',
			'avi-theme-admin',
			'avi-nav-admin',
			'avi-footer-admin',
			'avi-avi-control-center',
			'avi-automations-cron',
			'avi-install-core-tables',
			'avi-cron-test',
		);
		if ( in_array( $page, $avision_plugin_admin_slugs, true ) ) {
			return true;
		}
	}
	if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in()
		&& function_exists( 'current_user_can' ) && current_user_can( 'manage_options' ) ) {
		return true;
	}
	return false;
}

/**
 * God mode URI : aucune redirection « mur d’auth » (init / template_redirect) pour ces URLs — inspection brute de REQUEST_URI (query incluse).
 *
 * @return bool True = laisser passer sans login (rapport public ou lien partagé agence).
 */
function avision_auth_wall_uri_public_bypass() {
	$req_uri = isset( $_SERVER['REQUEST_URI'] )
		? ( function_exists( 'wp_unslash' ) ? (string) wp_unslash( (string) $_SERVER['REQUEST_URI'] ) : (string) $_SERVER['REQUEST_URI'] )
		: '';
	if ( $req_uri === '' ) {
		return false;
	}
	if ( strpos( $req_uri, '/report/' ) !== false ) {
		return true;
	}
        if ( strpos( $req_uri, 'bccc90f7-4f8e-11f1-8a83-fa163e75843f' ) !== false && ( ! function_exists( 'is_user_logged_in' ) || ! is_user_logged_in() ) ) {
                return true;
        }
    if ( strpos( $req_uri, '/demo-dashboard/' ) !== false ) {
		return true;
	}
	// ANTI-RÉGRESSION #204 [24 mai 2026] — agency_edit=1 bypass auth wall (alias shared_view)
	if ( strpos( $req_uri, 'agency_token=' ) !== false
		&& ( strpos( $req_uri, 'shared_view=1' ) !== false || strpos( $req_uri, 'agency_edit=1' ) !== false ) ) {
		return true;
	}
	return false;
}

/**
 * Rapport grey-label /report/{slug}/{id}/ : pas de mur d’auth WordPress (validation slug + profil côté thème Avision_Router).
 *
 * @return bool
 */
function avision_is_avi_client_report_public_route() {
	if ( function_exists( 'avision_auth_wall_uri_public_bypass' ) && avision_auth_wall_uri_public_bypass() ) {
		return true;
	}
	$p = avision_route_guard_get_request_path();
	if ( $p !== '' && strpos( $p, '/report/' ) !== false ) {
		return true;
	}
	if ( function_exists( 'get_query_var' ) && (string) get_query_var( 'avi_report' ) === '1' ) {
		return true;
	}
	// Lien de travail agence : ?shared_view=1&agency_token=… sur la page Premium uniquement (lecture seule ; jeton validé côté thème).
	if ( $p !== '' && strpos( $p, '/premium-dashboard' ) !== false ) {
		if ( isset( $_GET['shared_view'], $_GET['agency_token'] )
			&& function_exists( 'sanitize_text_field' )
			&& function_exists( 'wp_unslash' ) ) {
			$sv  = sanitize_text_field( wp_unslash( (string) $_GET['shared_view'] ) );
			$tok = sanitize_text_field( wp_unslash( (string) $_GET['agency_token'] ) );
			// ANTI-RÉGRESSION #201 [24 mai 2026] — agency_edit=1 = accès full edit agence (alias shared_view)
			if ( ( $sv === '1' || ( isset( $_GET['agency_edit'] ) && sanitize_text_field( wp_unslash( (string) $_GET['agency_edit'] ) ) === '1' ) ) && $tok !== '' ) {
				return true;
			}
		}
	}
	return false;
}

/**
 * Page « premium dashboard » : WP + inspection absolue de la requête HTTP (is_page peut échouer selon le thème).
 *
 * @return bool
 */
function avision_is_premium_dashboard_query() {
	if ( function_exists( 'is_admin' ) && is_admin() ) {
		return false;
	}

	$request_path = avision_route_guard_get_request_path();
	$by_uri       = ( $request_path !== '' && strpos( $request_path, '/premium-dashboard' ) !== false );

	if (
		( function_exists( 'is_page' ) && is_page( 'premium-dashboard' ) )
		|| ( function_exists( 'is_page_template' ) && is_page_template( 'page-premium-dashboard.php' ) )
		|| $by_uri
	) {
		return true;
	}

	$slug = function_exists( 'apply_filters' )
		? apply_filters( 'avision_premium_dashboard_page_slug', 'premium-dashboard' )
		: 'premium-dashboard';
	if ( function_exists( 'is_page' ) && is_string( $slug ) && $slug !== '' && $slug !== 'premium-dashboard' && is_page( $slug ) ) {
		return true;
	}

	return (bool) ( function_exists( 'apply_filters' )
		? apply_filters( 'avision_is_premium_dashboard_route', false )
		: false );
}

/**
 * Page « agency dashboard » : même logique que le premium (URI absolue + is_page + template + slug filtré).
 *
 * @return bool
 */
function avision_is_agency_dashboard_query() {
	if ( function_exists( 'is_admin' ) && is_admin() ) {
		return false;
	}

	$request_path = avision_route_guard_get_request_path();
	$by_uri       = ( $request_path !== '' && strpos( $request_path, '/agency-dashboard' ) !== false );

	if (
		( function_exists( 'is_page' ) && is_page( 'agency-dashboard' ) )
		|| ( function_exists( 'is_page_template' ) && is_page_template( 'page-agency-dashboard.php' ) )
		|| $by_uri
	) {
		return true;
	}

	$slug = function_exists( 'apply_filters' )
		? apply_filters( 'avision_agency_dashboard_page_slug', 'agency-dashboard' )
		: 'agency-dashboard';
	if ( function_exists( 'is_page' ) && is_string( $slug ) && $slug !== '' && $slug !== 'agency-dashboard' && is_page( $slug ) ) {
		return true;
	}

	return (bool) ( function_exists( 'apply_filters' )
		? apply_filters( 'avision_is_agency_dashboard_route', false )
		: false );
}

/**
 * Page onboarding B2B (/btob-onboarding/).
 *
 * @return bool
 */
function avision_is_btob_onboarding_query() {
	if ( function_exists( 'is_admin' ) && is_admin() ) {
		return false;
	}
	$request_path = avision_route_guard_get_request_path();
	$by_uri       = ( $request_path !== '' && strpos( $request_path, '/btob-onboarding' ) !== false );
	if ( $by_uri ) {
		return true;
	}
	$slug = function_exists( 'apply_filters' )
		? apply_filters( 'avision_btob_onboarding_page_slug', 'btob-onboarding' )
		: 'btob-onboarding';
	if ( function_exists( 'is_page' ) && is_string( $slug ) && $slug !== '' && is_page( $slug ) ) {
		return true;
	}
	return (bool) ( function_exists( 'apply_filters' )
		? apply_filters( 'avision_is_btob_onboarding_route', false )
		: false );
}

/**
 * Indique si un profil SaaS lié à l’utilisateur WP a un google_access_token renseigné.
 *
 * @param int $wp_user_id ID WordPress.
 * @return bool True si token présent sur au moins une ligne ; true si table/colonne absente (ne pas bloquer).
 */
function avision_b2b_user_has_google_access_token( $wp_user_id ) {
	global $wpdb;
	$wp_user_id = (int) $wp_user_id;
	if ( $wp_user_id <= 0 || ! isset( $wpdb ) || ! is_object( $wpdb ) ) {
		return false;
	}
	$table = 'wor1515_avi_saas_profiles';
	if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) !== $table ) {
		$table = $wpdb->prefix . 'avi_saas_profiles';
	}
	if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) !== $table ) {
		return true;
	}
	if ( $wpdb->get_var( $wpdb->prepare( "SHOW COLUMNS FROM `{$table}` LIKE %s", 'google_access_token' ) ) !== 'google_access_token' ) {
		return true;
	}
	if ( $wpdb->get_var( $wpdb->prepare( "SHOW COLUMNS FROM `{$table}` LIKE %s", 'wp_user_id' ) ) !== 'wp_user_id' ) {
		return true;
	}
	// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- nom de table validé ci-dessus.
	$tok = $wpdb->get_var(
		$wpdb->prepare(
			"SELECT google_access_token FROM `{$table}` WHERE wp_user_id = %d AND google_access_token IS NOT NULL AND TRIM(google_access_token) != '' ORDER BY id DESC LIMIT 1",
			$wp_user_id
		)
	);
	return is_string( $tok ) && trim( $tok ) !== '';
}

/**
 * Rediriger l’agence vers /btob-onboarding/ (premier login ou OAuth Google manquant).
 *
 * @param int $wp_user_id ID utilisateur connecté.
 * @return bool True = redirection requise.
 */
function avision_agency_must_redirect_to_btob_onboarding( $wp_user_id ) {
	$wp_user_id = (int) $wp_user_id;
	if ( $wp_user_id <= 0 ) {
		return false;
	}
	if ( (bool) apply_filters( 'avision_skip_agency_btob_onboarding_redirect', false, $wp_user_id ) ) {
		return false;
	}
	$user = function_exists( 'get_userdata' ) ? get_userdata( $wp_user_id ) : null;
	if ( ! $user || ! $user->exists() ) {
		return false;
	}
	if ( function_exists( 'user_can' ) && user_can( $user, 'manage_options' ) ) {
		return false;
	}
	if ( ! in_array( 'avi_agency', (array) $user->roles, true ) ) {
		return false;
	}
	if ( function_exists( 'get_user_meta' ) && get_user_meta( $wp_user_id, 'avi_b2b_onboarding_completed', true ) === '1' ) {
		return false;
	}
	$first_login = false;
	if ( isset( $_GET['first_login'] ) && function_exists( 'sanitize_text_field' ) && function_exists( 'wp_unslash' ) ) {
		$first_login = sanitize_text_field( wp_unslash( (string) $_GET['first_login'] ) ) === '1';
	}
	if ( $first_login ) {
		return true;
	}
	$master = function_exists( 'get_user_meta' ) ? get_user_meta( $wp_user_id, 'is_agency_master', true ) : '';
	// GARDE ABSOLUE B2C : jamais redirect agency si avi_user_type=b2c
	$avi_user_type = function_exists( 'get_user_meta' ) ? get_user_meta( $wp_user_id, 'avi_user_type', true ) : '';
	if ( $avi_user_type === 'b2c' ) {
		return false;
	}
	if ( $master === '' || $master === false ) {
		return true;
	}
	if ( ! function_exists( 'avision_b2b_user_has_google_access_token' ) || ! avision_b2b_user_has_google_access_token( $wp_user_id ) ) {
		return true;
	}
	return false;
}

/**
 * Accès route / shortcode agence : manage_options ou rôle avi_agency (pas agency_admin).
 *
 * @param int|null $user_id ID utilisateur ou null = courant.
 * @return bool
 */
function avision_user_can_access_agency_dashboard_route( $user_id = null ) {
	$uid = $user_id !== null ? (int) $user_id : (int) get_current_user_id();
	if ( $uid <= 0 ) {
		return (bool) apply_filters( 'avision_agency_dashboard_route_allow_access', false, $uid );
	}
	$user = function_exists( 'get_userdata' ) ? get_userdata( $uid ) : null;
	if ( ! $user || ! $user->exists() ) {
		return (bool) apply_filters( 'avision_agency_dashboard_route_allow_access', false, $uid );
	}
	if ( function_exists( 'user_can' ) && user_can( $user, 'manage_options' ) ) {
		return true;
	}
	if ( in_array( 'avi_agency', (array) $user->roles, true ) ) {
		return true;
	}
	return (bool) apply_filters( 'avision_agency_dashboard_route_allow_access', false, $uid );
}

/**
 * Le pid en query correspond au profil de l’utilisateur (évite redirection en boucle).
 *
 * @param string $uuid UUID attendu (utilisateur courant).
 * @return bool
 */
function avision_premium_route_pid_matches_user( $uuid ) {
	$uuid = is_string( $uuid ) ? strtolower( trim( $uuid ) ) : '';
	if ( $uuid === '' ) {
		return false;
	}
	$raw = '';
	if ( isset( $_GET['pid'] ) && function_exists( 'sanitize_text_field' ) && function_exists( 'wp_unslash' ) ) {
		$raw = sanitize_text_field( wp_unslash( (string) $_GET['pid'] ) );
	} elseif ( isset( $_GET['pid'] ) ) {
		$raw = (string) $_GET['pid'];
	}
	$raw = strtolower( trim( $raw ) );
	if ( $raw === '' || ! preg_match( '/^[a-f0-9\-]{32,36}$/i', $raw ) ) {
		return false;
	}
	return $raw === $uuid;
}

/**
 * Journal de diagnostic avant toute redirection du route guard (identifier les dérives vers premium-dashboard, etc.).
 *
 * @param int    $line   Passer __LINE__ à l’appel pour localiser l’emplacement exact.
 * @param string $reason Motif court (machine-readable).
 * @return void
 */
function avision_route_guard_log_redirect_intent( $line, $reason ) {
	if ( ! function_exists( 'error_log' ) ) {
		return;
	}
	$uri = isset( $_SERVER['REQUEST_URI'] )
		? ( function_exists( 'wp_unslash' ) ? (string) wp_unslash( (string) $_SERVER['REQUEST_URI'] ) : (string) $_SERVER['REQUEST_URI'] )
		: '';
	$page = '(none)';
	if ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) && function_exists( 'sanitize_text_field' ) && function_exists( 'wp_unslash' ) ) {
		$page = sanitize_text_field( wp_unslash( $_GET['page'] ) );
	} elseif ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) ) {
		$page = $_GET['page'];
	}
	error_log(
		sprintf(
			'[AVI DEBUG] Redirect triggered from line %d because page is %s | reason=%s | uri=%s',
			(int) $line,
			$page,
			(string) $reason,
			$uri
		)
	);
}

/**
 * Garde absolue cockpits Premium + Agency : visiteur sur /premium-dashboard ou /agency-dashboard → /login/ + redirect_to.
 * Hook init (priorité -100) : avant le thème (ex. init -1), bypass URI public (`avision_auth_wall_uri_public_bypass`) en tête.
 * Exception : retour Stripe Hosted Checkout (?session_id=cs_… ou cs_test_…) — laisser avision_stripe_success_auto_login_bridge (init 5) lire la session, inscrire et connecter.
 *
 * @return void
 */
function avision_hard_guard_premium_dashboard_unauthenticated() {
	if ( function_exists( 'is_admin' ) && is_admin() ) {
		return;
	}
	// Administration WP + manage_options (+ filet URI wp-admin / wp-login.php) : aucune redirection cockpit.
	if ( function_exists( 'avision_route_guard_bypass_administration_context' ) && avision_route_guard_bypass_administration_context() ) {
		return;
	}

	// Super-admin / rôle administrator sans capa modifiée : même filet que l’historique.
	if ( function_exists( 'avision_route_guard_is_privileged_wp_user' ) && avision_route_guard_is_privileged_wp_user() ) {
		return;
	}

	// 1. Bypass absolu pour les URLs de connexion (évite la boucle infinie)
	$current_uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
	if ( strpos( $current_uri, 'wp-login.php' ) !== false || strpos( $current_uri, '/login' ) !== false || strpos( $current_uri, '/connexion' ) !== false ) {
		return;
	}

	if ( ! function_exists( 'is_user_logged_in' ) ) {
		return;
	}
	if ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
		return;
	}
	if ( function_exists( 'wp_doing_cron' ) && wp_doing_cron() ) {
		return;
	}
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}
	if ( function_exists( 'avision_auth_wall_uri_public_bypass' ) && avision_auth_wall_uri_public_bypass() ) {
		return;
	}
	if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
		return;
	}
	if ( function_exists( 'avision_is_avi_client_report_public_route' ) && avision_is_avi_client_report_public_route() ) {
		return;
	}
	$request_path = avision_route_guard_get_request_path();
	$on_premium   = ( $request_path !== '' && strpos( $request_path, '/premium-dashboard' ) !== false );
	$on_agency    = ( $request_path !== '' && strpos( $request_path, '/agency-dashboard' ) !== false );
	$on_btob      = ( $request_path !== '' && strpos( $request_path, '/btob-onboarding' ) !== false );
	if ( ! $on_premium && ! $on_agency && ! $on_btob ) {
		return;
	}
	// Flux reset / activation (liens e-mail) : ne pas rediriger vers /login/ si key+login sont présents (évite perte de query + cache).
	if ( function_exists( 'avision_auth_is_password_reset_guest_flow' ) && avision_auth_is_password_reset_guest_flow() ) {
		return;
	}
	if ( ! is_user_logged_in() && ! empty( $_GET['key'] ) && ! empty( $_GET['login'] )
		&& function_exists( 'sanitize_text_field' ) && function_exists( 'wp_unslash' ) ) {
		$gk = sanitize_text_field( wp_unslash( (string) $_GET['key'] ) );
		$gl = trim( (string) wp_unslash( (string) $_GET['login'] ) );
		if ( $gk !== '' && $gl !== '' && strlen( $gk ) >= 12 ) {
			return;
		}
	}
	$uri = function_exists( 'wp_unslash' ) ? wp_unslash( (string) $_SERVER['REQUEST_URI'] ) : (string) $_SERVER['REQUEST_URI'];
	// Retour paiement Stripe (cs_… incl. cs_test_…, cs_live_…) : ne pas court-circuiter avant le bridge (init 5).
	if ( ! empty( $_GET['session_id'] ) && is_string( $_GET['session_id'] ) && function_exists( 'sanitize_text_field' ) && function_exists( 'wp_unslash' ) ) {
		$sid = sanitize_text_field( wp_unslash( $_GET['session_id'] ) );
		if ( $sid !== '' && strpos( $sid, 'cs_' ) === 0 ) {
			return;
		}
	}
	// Auto-login token post-Stripe : laisser avision_auto_login_token_init (init -101) connecter l'user.
	if ( ! empty( $_GET['avi_alt'] ) && is_string( $_GET['avi_alt'] ) ) {
		$alt = sanitize_text_field( wp_unslash( $_GET['avi_alt'] ) );
		if ( strlen( $alt ) >= 16 ) {
			return;
		}
	}
	// POST sur btob-onboarding (soumission formulaire agence) : laisser template_redirect:5 traiter.
	if ( isset( $_SERVER['REQUEST_METHOD'] ) && strtoupper( (string) $_SERVER['REQUEST_METHOD'] ) === 'POST'
		&& ! empty( $_POST['avision_btob_onboarding_submit'] ) && $on_btob ) {
		return;
	}
	if ( is_user_logged_in() ) {
		return;
	}
	$login_url = function_exists( 'apply_filters' )
		? apply_filters( 'avision_dashboard_guard_login_url', trailingslashit( home_url( '/login/' ) ) )
		: trailingslashit( home_url( '/login/' ) );
	$redirect_to = '';
	if ( $uri !== '' && isset( $uri[0] ) && $uri[0] === '/' && function_exists( 'home_url' ) ) {
		$redirect_to = home_url( $uri );
		if ( function_exists( 'wp_validate_redirect' ) ) {
			$redirect_to = wp_validate_redirect( $redirect_to, '' );
		}
		$redirect_to = is_string( $redirect_to ) ? $redirect_to : '';
	}
	$target = $login_url;
	if ( $redirect_to !== '' && function_exists( 'add_query_arg' ) ) {
		$target = add_query_arg( 'redirect_to', $redirect_to, $login_url );
	}
	if ( ! headers_sent() && function_exists( 'wp_safe_redirect' ) ) {
		avision_route_guard_log_redirect_intent( __LINE__, 'hard_guard_unauthenticated_to_login' );
		wp_safe_redirect( $target );
		exit;
	}
	if ( function_exists( 'nocache_headers' ) ) {
		nocache_headers();
	}
	if ( function_exists( 'wp_die' ) ) {
		wp_die(
			esc_html__( 'You must be logged in to view this page.', 'avision-dashboard' ),
			esc_html__( 'Authentication required', 'avision-dashboard' ),
			array( 'response' => 403 )
		);
	}
	exit;
}

/**
 * template_redirect : garde premium (login, PID, ?pid=) et agence (login, avi_agency / manage_options).
 * Priorité -100 : bypass URI public (`avision_auth_wall_uri_public_bypass`) exécuté en tout premier dans le callback.
 *
 * @return void
 */
function avision_template_redirect_secure_dashboard_routes() {
	if ( function_exists( 'is_admin' ) && is_admin() ) {
		return;
	}
	// Administration WP + manage_options (+ filet URI wp-admin / wp-login.php) : aucune redirection cockpit.
	if ( function_exists( 'avision_route_guard_bypass_administration_context' ) && avision_route_guard_bypass_administration_context() ) {
		return;
	}

	if ( function_exists( 'avision_route_guard_is_privileged_wp_user' ) && avision_route_guard_is_privileged_wp_user() ) {
		return;
	}

	// 1. Bypass absolu pour les URLs de connexion (évite la boucle infinie)
	$current_uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
	if ( strpos( $current_uri, 'wp-login.php' ) !== false || strpos( $current_uri, '/login' ) !== false || strpos( $current_uri, '/connexion' ) !== false ) {
		return;
	}

	if ( function_exists( 'avision_auth_wall_uri_public_bypass' ) && avision_auth_wall_uri_public_bypass() ) {
		return;
	}
	if ( ! function_exists( 'is_user_logged_in' ) ) {
		return;
	}
	if ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
		return;
	}
	if ( function_exists( 'wp_doing_cron' ) && wp_doing_cron() ) {
		return;
	}
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}

	// Pages login / activation avec ?key= & ?login= : pas de redirection « cockpit » qui casserait le flux invité.
	if ( function_exists( 'avision_auth_is_password_reset_guest_flow' ) && avision_auth_is_password_reset_guest_flow() ) {
		return;
	}

	if ( function_exists( 'avision_is_avi_client_report_public_route' ) && avision_is_avi_client_report_public_route() ) {
		return;
	}

	$is_premium = avision_is_premium_dashboard_query();
	$is_agency  = avision_is_agency_dashboard_query();
	$is_btob    = avision_is_btob_onboarding_query();
	if ( ! $is_premium && ! $is_agency && ! $is_btob ) {
		return;
	}

	$login_url = function_exists( 'apply_filters' )
		? apply_filters( 'avision_dashboard_guard_login_url', trailingslashit( home_url( '/login/' ) ) )
		: trailingslashit( home_url( '/login/' ) );

	// Auto-login token post-Stripe : bypass si avi_alt présent et valide.
	if ( ! empty( $_GET['avi_alt'] ) && is_string( $_GET['avi_alt'] ) ) {
		$alt = sanitize_text_field( wp_unslash( $_GET['avi_alt'] ) );
		if ( strlen( $alt ) >= 16 ) {
			return;
		}
	}
	// POST formulaire btob-onboarding : laisser template_redirect:5 traiter.
	if ( isset( $_SERVER['REQUEST_METHOD'] ) && strtoupper( (string) $_SERVER['REQUEST_METHOD'] ) === 'POST'
		&& ! empty( $_POST['avision_btob_onboarding_submit'] ) && $is_btob ) {
		return;
	}
	if ( ! is_user_logged_in() ) {
		// Aucun bypass : visiteur → connexion obligatoire. Reprise d’URL complète (ex. ?pid=) après login.
		$redirect_to = '';
		if ( function_exists( 'home_url' ) && isset( $_SERVER['REQUEST_URI'] ) ) {
			$request_path = function_exists( 'wp_unslash' )
				? wp_unslash( (string) $_SERVER['REQUEST_URI'] )
				: (string) $_SERVER['REQUEST_URI'];
			if ( $request_path !== '' && isset( $request_path[0] ) && $request_path[0] === '/' ) {
				$candidate = home_url( $request_path );
				if ( function_exists( 'wp_validate_redirect' ) ) {
					$candidate = wp_validate_redirect( $candidate, '' );
				}
				$redirect_to = is_string( $candidate ) ? $candidate : '';
			}
		}
		$target = $login_url;
		if ( $redirect_to !== '' && function_exists( 'add_query_arg' ) ) {
			$target = add_query_arg( 'redirect_to', $redirect_to, $login_url );
		}
		if ( ! headers_sent() && function_exists( 'wp_safe_redirect' ) ) {
			avision_route_guard_log_redirect_intent( __LINE__, 'template_not_logged_to_login' );
			wp_safe_redirect( $target );
			exit;
		}
		if ( function_exists( 'nocache_headers' ) ) {
			nocache_headers();
		}
		if ( function_exists( 'wp_die' ) ) {
			wp_die(
				esc_html__( 'You must be logged in to view this page.', 'avision-dashboard' ),
				esc_html__( 'Authentication required', 'avision-dashboard' ),
				array( 'response' => 403 )
			);
		}
		exit;
	}

	// Onboarding B2B : réservé aux comptes agence (ou administrateurs).
	if ( $is_btob ) {
		$wp_uid = (int) get_current_user_id();
		$u      = function_exists( 'get_userdata' ) ? get_userdata( $wp_uid ) : null;
		if ( $u && $u->exists() ) {
			$is_agency_role = in_array( 'avi_agency', (array) $u->roles, true );
			$is_admin_cap   = function_exists( 'user_can' ) && user_can( $u, 'manage_options' );
			if ( ! $is_agency_role && ! $is_admin_cap ) {
				$premium_home = function_exists( 'apply_filters' )
					? apply_filters( 'avision_premium_dashboard_canonical_url', trailingslashit( home_url( '/premium-dashboard/' ) ) )
					: trailingslashit( home_url( '/premium-dashboard/' ) );
				if ( ! headers_sent() && function_exists( 'wp_safe_redirect' ) ) {
					avision_route_guard_log_redirect_intent( __LINE__, 'template_b2b_forbidden_to_premium' );
					wp_safe_redirect( $premium_home );
					exit;
				}
			}
		}
		return;
	}

	if ( $is_premium ) {
		if ( ! function_exists( 'avision_get_saas_profile_uuid_for_wp_user' ) ) {
			return;
		}
		$wp_uid = (int) get_current_user_id();
		$uuid   = avision_get_saas_profile_uuid_for_wp_user( $wp_uid );
		$audit  = function_exists( 'apply_filters' )
			? apply_filters( 'avision_premium_dashboard_guard_audit_url', trailingslashit( home_url( '/local-audit/' ) ) )
			: trailingslashit( home_url( '/local-audit/' ) );

		if ( $uuid === '' ) {
			if ( ! headers_sent() && function_exists( 'wp_safe_redirect' ) ) {
				avision_route_guard_log_redirect_intent( __LINE__, 'template_premium_no_uuid_to_audit' );
				wp_safe_redirect( $audit );
				exit;
			}
			return;
		}

		if ( avision_premium_route_pid_matches_user( $uuid ) ) {
			return;
		}

		if ( ! headers_sent() && function_exists( 'wp_safe_redirect' ) && function_exists( 'add_query_arg' ) ) {
			$target = add_query_arg( 'pid', rawurlencode( $uuid ) );
			$target = function_exists( 'apply_filters' )
				? apply_filters( 'avision_premium_dashboard_guard_pid_redirect_url', $target, $uuid )
				: $target;
			avision_route_guard_log_redirect_intent( __LINE__, 'template_premium_pid_normalize' );
			wp_safe_redirect( $target );
			exit;
		}
		return;
	}

	if ( $is_agency ) {
		$premium_fallback = function_exists( 'apply_filters' )
			? apply_filters( 'avision_agency_guard_redirect_premium_url', trailingslashit( home_url( '/premium-dashboard/' ) ) )
			: trailingslashit( home_url( '/premium-dashboard/' ) );
		if ( ! avision_user_can_access_agency_dashboard_route() ) {
			if ( ! headers_sent() && function_exists( 'wp_safe_redirect' ) ) {
				avision_route_guard_log_redirect_intent( __LINE__, 'template_agency_forbidden_to_premium' );
				wp_safe_redirect( $premium_fallback );
				exit;
			}
		}
		$wp_uid = (int) get_current_user_id();
		if ( function_exists( 'avision_agency_must_redirect_to_btob_onboarding' ) && avision_agency_must_redirect_to_btob_onboarding( $wp_uid ) ) {
			$onboarding_url = function_exists( 'apply_filters' )
				? apply_filters( 'avision_agency_btob_onboarding_redirect_url', trailingslashit( home_url( '/btob-onboarding/' ) ) )
				: trailingslashit( home_url( '/btob-onboarding/' ) );
			if ( is_string( $onboarding_url ) && $onboarding_url !== '' && ! headers_sent() && function_exists( 'wp_safe_redirect' ) ) {
				avision_route_guard_log_redirect_intent( __LINE__, 'template_agency_to_btob_onboarding' );
				wp_safe_redirect( $onboarding_url );
				exit;
			}
		}
	}
}

add_action( 'init', 'avision_hard_guard_premium_dashboard_unauthenticated', -100 );
add_action( 'template_redirect', 'avision_template_redirect_secure_dashboard_routes', -100 );
