<?php
/**
 * Role-to-scheme resolution with deterministic priority.
 *
 * @package WP_PowerSuite\AdminColorCustomizer
 */

namespace WP_PowerSuite\AdminColorCustomizer;

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

class Role_Resolver {

	/**
	 * Load wp-admin role helpers and return editable roles.
	 *
	 * `get_editable_roles()` lives in wp-admin/includes/user.php. Call it
	 * immediately after require_once. An unqualified call would resolve to
	 * this namespace and fatal.
	 *
	 * @return array<string, mixed>
	 */
	public static function get_editable_roles(): array {
		require_once ABSPATH . 'wp-admin/includes/user.php';
		$roles = \get_editable_roles();
		if ( is_array( $roles ) ) {
			return $roles;
		}

		if ( function_exists( '\wp_roles' ) ) {
			$names = \wp_roles()->get_names();
			return is_array( $names ) ? $names : [];
		}

		return [];
	}

	/**
	 * @return list<string>
	 */
	public static function get_editable_role_keys(): array {
		return array_map( 'strval', array_keys( self::get_editable_roles() ) );
	}

	/**
	 * @return list<string>
	 */
	public static function get_role_priority(): array {
		$default = [
			'administrator',
			'editor',
			'author',
			'contributor',
			'subscriber',
		];

		$editable = self::get_editable_role_keys();
		$custom   = array_values(
			array_diff(
				array_map( 'strval', $editable ),
				$default
			)
		);
		sort( $custom, SORT_STRING );

		$priority = array_merge( $default, $custom );

		/** @var list<string> $filtered */
		$filtered = apply_filters( 'wpps_admin_color_customizer_role_priority', $priority );

		$filtered = array_values(
			array_filter(
				array_map( 'sanitize_key', $filtered ),
				static fn( string $role ): bool => $role !== '' && in_array( $role, $editable, true )
			)
		);

		return $filtered !== [] ? $filtered : $priority;
	}

	/**
	 * @param array<string, mixed> $settings
	 */
	public static function resolve_scheme_id_for_user( int $user_id, array $settings ): ?string {
		$user = get_userdata( $user_id );
		if ( ! $user instanceof \WP_User ) {
			return null;
		}

		$role_schemes = is_array( $settings['role_schemes'] ?? null ) ? $settings['role_schemes'] : [];
		if ( $role_schemes === [] ) {
			return null;
		}

		$registry = Scheme_Registry::instance();
		$valid    = $registry->get_all_scheme_ids( $settings );
		$user_roles = (array) $user->roles;

		foreach ( self::get_role_priority() as $role ) {
			if ( ! in_array( $role, $user_roles, true ) ) {
				continue;
			}
			if ( ! isset( $role_schemes[ $role ] ) ) {
				continue;
			}
			$scheme_id = sanitize_key( (string) $role_schemes[ $role ] );
			if ( in_array( $scheme_id, $valid, true ) ) {
				return $scheme_id;
			}
		}

		return null;
	}
}
