<?php
/**
 * Admin Color Customizer premium — packed only in the Pro add-on overlay.
 *
 * Secure design (rafter-secure-design):
 * - Identity: WordPress site admins managing dashboard colors. No new auth.
 * - AuthZ: Custom schemes, force-all / force-by-role, and role mapping live
 *   in this file. Lite cannot run it; Freemium::unlocked requires Pro + license.
 * - Input: scheme colors stay hex-only; custom CSS still goes through
 *   Settings::sanitize_custom_css().
 *
 * @package WP_PowerSuite\AdminColorCustomizer
 */

namespace WP_PowerSuite\AdminColorCustomizer;

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

/**
 * Custom schemes, forced modes, and role mapping.
 */
final class Premium {

	/**
	 * @param array<string, array<string, mixed>> $built_in
	 * @param array<string, mixed>                $settings
	 * @return array<string, array<string, mixed>>
	 */
	public static function merge_custom_schemes( array $built_in, array $settings ): array {
		$custom = is_array( $settings['custom_schemes'] ?? null ) ? $settings['custom_schemes'] : [];

		return array_merge( $built_in, $custom );
	}

	/**
	 * @param array<string, mixed> $scheme
	 * @return array<string, mixed>|null
	 */
	public static function sanitize_scheme( array $scheme, string $context = 'save' ): ?array {
		$id = isset( $scheme['id'] ) ? sanitize_key( (string) $scheme['id'] ) : '';
		if ( $id === '' || ! preg_match( '/^[a-z0-9_]{1,64}$/', $id ) ) {
			return null;
		}

		if ( ! empty( $scheme['built_in'] ) ) {
			return null;
		}

		$color_keys = [
			'primary',
			'secondary',
			'accent',
			'menu_bg',
			'menu_text',
			'menu_hover_bg',
			'menu_hover_text',
			'toolbar_bg',
			'toolbar_text',
			'button_bg',
			'button_text',
			'notice',
		];

		$sanitized = [
			'id'       => $id,
			'name'     => sanitize_text_field( (string) ( $scheme['name'] ?? $id ) ),
			'built_in' => false,
		];

		if ( $sanitized['name'] === '' ) {
			return null;
		}

		foreach ( $color_keys as $key ) {
			$color = Scheme_Registry::sanitize_hex_color( $scheme[ $key ] ?? '' );
			if ( $color === null ) {
				return null;
			}
			$sanitized[ $key ] = $color;
		}

		$sanitized['custom_css'] = '';
		if ( ! empty( $scheme['custom_css'] ) && is_string( $scheme['custom_css'] ) && $context !== 'import' ) {
			$sanitized['custom_css'] = Settings::sanitize_custom_css( $scheme['custom_css'] );
		}

		return $sanitized;
	}

	/**
	 * @param mixed $raw
	 * @return array<string, array<string, mixed>>
	 */
	public static function sanitize_custom_schemes( $raw, string $context ): array {
		if ( ! is_array( $raw ) ) {
			return [];
		}

		$custom_schemes = [];
		foreach ( $raw as $scheme_id => $scheme ) {
			if ( ! is_array( $scheme ) ) {
				continue;
			}
			$sanitized_scheme = self::sanitize_scheme( array_merge( $scheme, [ 'id' => $scheme_id ] ), $context );
			if ( $sanitized_scheme !== null && empty( $sanitized_scheme['built_in'] ) ) {
				$custom_schemes[ $sanitized_scheme['id'] ] = $sanitized_scheme;
			}
		}

		return array_slice( $custom_schemes, 0, 50, true );
	}

	/**
	 * @param mixed        $raw
	 * @param list<string> $valid_ids
	 * @return array<string, string>
	 */
	public static function sanitize_role_schemes( $raw, array $valid_ids ): array {
		if ( ! is_array( $raw ) ) {
			return [];
		}

		$role_schemes = [];
		$editable     = array_keys( get_editable_roles() );
		foreach ( $raw as $role => $scheme_id ) {
			$role_key   = sanitize_key( (string) $role );
			$scheme_key = sanitize_key( (string) $scheme_id );
			if ( $role_key === '' || ! in_array( $role_key, $editable, true ) ) {
				continue;
			}
			if ( ! in_array( $scheme_key, $valid_ids, true ) ) {
				continue;
			}
			$role_schemes[ $role_key ] = $scheme_key;
		}

		return $role_schemes;
	}

	/**
	 * @param array<string, mixed> $settings
	 */
	public static function resolve_forced_scheme_id( string $mode, int $user_id, array $settings, string $fallback ): string {
		if ( $mode === 'force_by_role' && class_exists( Role_Resolver::class, false ) ) {
			return Role_Resolver::resolve_scheme_id_for_user( $user_id, $settings ) ?? $fallback;
		}

		return $fallback;
	}

	/**
	 * @param array<string, mixed> $scheme
	 * @param array<string, mixed> $overrides
	 * @return array<string, mixed>
	 */
	public static function apply_color_overrides( array $scheme, array $overrides ): array {
		$keys = [
			'primary',
			'secondary',
			'accent',
			'menu_bg',
			'menu_text',
			'menu_hover_bg',
			'menu_hover_text',
			'toolbar_bg',
			'toolbar_text',
			'button_bg',
			'button_text',
			'notice',
		];

		foreach ( $keys as $key ) {
			if ( ! isset( $overrides[ $key ] ) ) {
				continue;
			}
			$color = Scheme_Registry::sanitize_hex_color( $overrides[ $key ] );
			if ( $color !== null ) {
				$scheme[ $key ] = $color;
			}
		}

		return $scheme;
	}
}
