<?php
/**
 * Accounts Module
 *
 * Initializes roles/capabilities and enforces interface access separation.
 *
 * @package AmbassadorHub\Accounts
 */

namespace AmbassadorHub\Accounts;

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

use AmbassadorHub\Accounts\Admin\Settings\SettingsManager;
use AmbassadorHub\Accounts\MigrationRunner;
use AmbassadorHub\Privacy\Privacy;

/**
 * Handles accounts bootstrap for the plugin.
 */
final class AccountsModule {
	/**
	 * Initialize the Accounts module.
	 *
	 * @return void
	 */
	public static function init(): void {

		// Register database migrations for the Accounts module.
		MigrationRunner::init();

		// Ensure roles exist and are up to date.
		add_action( 'init', array( Roles::class, 'ensure_roles' ) );

		// Listen for ambassador role additions and fire module-specific hook.
		add_action( 'add_user_role', array( self::class, 'on_user_role_added' ), 10, 2 );

		// Register automation triggers, conditions, and event handlers.
		Automations::init();

		// Initialize email verification system.
		EmailVerification::init();

		// Register Accounts REST API routes.
		AccountsApi::init();

		// Register account settings (page configuration, etc).
		SettingsManager::init();

		// Initialize profile picture handler.
		ProfilePicture::init();

		// Register Accounts admin submenu.
		Admin\Menu::init();

		// Initialize Gutenberg blocks and frontend content handlers.
		self::register_blocks();

		// Activation / deactivation lifecycle.
		add_action( 'ambh_activate', array( self::class, 'on_activate' ) );
		add_action( 'ambh_deactivate', array( self::class, 'on_deactivate' ) );

		// Enforce access separation: ambassadors never access wp-admin.
		add_action( 'admin_init', array( self::class, 'enforce_admin_access' ) );

		// Replace the WordPress login/logout URLs with the custom frontend page.
		add_filter( 'login_url', array( self::class, 'filter_login_url' ), 10, 3 );
		add_filter( 'logout_redirect', array( self::class, 'filter_logout_redirect' ), 10, 1 );

		// Register WordPress Privacy API exporter and eraser.
		Privacy::init();

		/**
		 * Fires when accounts module is initialized.
		 *
		 * @since 0.1.0
		 */
		do_action( 'ambh_accounts_module_init' );
	}

	/**
	 * Register all Gutenberg blocks and frontend content handlers for this module.
	 *
	 * @return void
	 */
	private static function register_blocks(): void {
		Blocks\Account\Block::init();
		Blocks\Account\ContentHandler::init();
		Blocks\Signup\Block::init();
	}

	/**
	 * Plugin activation: register roles and capabilities.
	 *
	 * @return void
	 */
	public static function on_activate(): void {
		Roles::register();
	}

	/**
	 * Plugin deactivation: currently no destructive action.
	 * We keep roles to avoid orphaning users.
	 *
	 * @return void
	 */
	public static function on_deactivate(): void {
		// Intentionally left blank.
	}

	/**
	 * Redirect ambassadors away from wp-admin to the frontend portal.
	 * Portal URL can be filtered via `ambh_portal_url`.
	 *
	 * @return void
	 */
	public static function enforce_admin_access(): void {
		global $pagenow;

		// admin-post.php is a form-handling endpoint, not an admin UI page.
		// It fires admin_init before dispatching the action, so bailing here
		// lets donation, signup, and login form submissions go through.
		if ( 'admin-post.php' === $pagenow ) {
			return;
		}

		if ( ! is_user_logged_in() ) {
			return;
		}

		$user = wp_get_current_user();
		if ( empty( $user ) || empty( $user->roles ) ) {
			return;
		}

		if ( in_array( Roles::ROLE_AMBASSADOR, $user->roles, true ) ) {
			$default_url = SettingsManager::get_account_page_url();

			/**
			 * Filter the frontend portal URL used for ambassador redirects.
			 *
			 * @param string $url Portal URL.
			 */
			$portal_url = apply_filters( 'ambh_portal_url', $default_url );
			wp_safe_redirect( $portal_url );
			exit;
		}
	}

	/**
	 * Replace wp-login.php with the custom frontend login page.
	 *
	 * Hooked to `login_url` so every call to `wp_login_url()` — including
	 * WordPress core's `auth_redirect()` — points ambassadors to the portal
	 * instead of wp-login.php.
	 *
	 * @param string $login_url    Default WordPress login URL.
	 * @param string $redirect     URL to redirect to after login (may be empty).
	 * @param bool   $force_reauth Whether to force re-authentication.
	 *
	 * @return string
	 */
	public static function filter_login_url( string $login_url, string $redirect, bool $force_reauth ): string { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- required by login_url filter signature.
		$page_id = SettingsManager::get_login_page_id();
		if ( ! $page_id ) {
			return $login_url;
		}

		// When the redirect target is a wp-admin URL, preserve the native
		// wp-login.php flow so backend-capable users are not funnelled through
		// the frontend form.  Sending them there causes a loop: they land on
		// the frontend after login instead of wp-admin, and on subsequent admin
		// visits auth_redirect() fires again, sending them back to the frontend.
		if ( $redirect && str_contains( $redirect, '/wp-admin' ) ) {
			return $login_url;
		}

		$url = (string) get_permalink( $page_id );
		if ( $redirect ) {
			$url = add_query_arg( 'redirect_to', rawurlencode( $redirect ), $url );
		}

		return $url;
	}

	/**
	 * Redirect to the custom login page after logout instead of wp-login.php.
	 *
	 * @param string $redirect_to The redirect destination URL.
	 *
	 * @return string
	 */
	public static function filter_logout_redirect( string $redirect_to ): string { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found -- required by logout_redirect filter signature.
		return SettingsManager::get_login_page_url();
	}

	public static function on_user_role_added( int $user_id, string $role ): void {

		if ( Roles::ROLE_AMBASSADOR === $role ) {
			// Invalidate relevant transients when a new ambassador is added.
			AccountsTransient::bump_version();

			do_action( 'ambh_ambassador_role_added', $user_id );
			return;
		}

		// Extend here for other roles if needed in the future.
	}
}
