<?php
/**
 * Settings defaults, sanitization, and multisite resolution.
 *
 * @package WP_PowerSuite\AdminColorCustomizer
 */

namespace WP_PowerSuite\AdminColorCustomizer;

use WP_PowerSuite\Core\NetworkScope;
use WP_PowerSuite\Core\OptionStoreModuleSettingsRepository;

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

class Settings {

	public const MODULE_ID = 'admin-color-customizer';

	public const VERSION = '1.0.14';

	public const MODES = [
		'disabled',
		'global_default',
		'force_all',
		'force_by_role',
		'per_user_selectable',
	];

	public const SCOPES = [
		'admin_only',
		'admin_and_admin_bar',
	];

	/**
	 * @return array<string, mixed>
	 */
	public static function get_default_settings(): array {
		return [
			'enabled'                 => true,
			'mode'                    => 'global_default',
			'scope'                   => 'admin_only',
			'active_scheme'           => 'powersuite_blue',
			'force_scheme'            => false,
			'role_schemes'            => [],
			'custom_schemes'          => [],
			'allow_custom_css'        => false,
			'custom_css'              => '',
			'environment_badge'       => [
				'enabled'         => false,
				'type'            => 'production',
				'label'           => '',
				'color'           => '#cc0000',
				'apply_bar_color' => false,
			],
			'frontend_admin_bar'      => false,
			'login_screen'            => false,
			'version'                 => self::VERSION,
			'use_network_default'     => false,
			'network_default_enabled' => false,
			'network_force_enabled'   => false,
		];
	}

	/**
	 * Whether the module is emergency-disabled via constant.
	 */
	public static function is_emergency_disabled(): bool {
		return defined( 'WPPS_DISABLE_ADMIN_COLOR_CUSTOMIZER' ) && WPPS_DISABLE_ADMIN_COLOR_CUSTOMIZER;
	}

	/**
	 * @return array<string, mixed>
	 */
	/**
	 * Raw stored site settings (not sanitized / not tier-limited).
	 *
	 * @return array<string, mixed>
	 */
	public static function get_stored_settings(): array {
		$stored = OptionStoreModuleSettingsRepository::forModule( self::MODULE_ID )->all( [] );

		return is_array( $stored ) ? $stored : [];
	}

	public static function get_site_settings(): array {
		$stored = OptionStoreModuleSettingsRepository::forModule( self::MODULE_ID )->all( self::get_default_settings() );

		return self::sanitize( is_array( $stored ) ? $stored : [] );
	}

	/**
	 * @return array<string, mixed>
	 */
	public static function get_network_settings(): array {
		if ( ! NetworkScope::isNetworkActivated() ) {
			return self::get_default_settings();
		}

		$all = NetworkScope::getPluginOption( 'wp_powersuite_settings', [] );
		$stored = is_array( $all ) && isset( $all[ self::MODULE_ID ] ) && is_array( $all[ self::MODULE_ID ] )
			? $all[ self::MODULE_ID ]
			: self::get_default_settings();

		return self::sanitize( $stored, 'network' );
	}

	/**
	 * Resolve effective settings for the current request context.
	 *
	 * @return array<string, mixed>
	 */
	public static function get_effective_settings(): array {
		if ( self::is_emergency_disabled() ) {
			return self::get_default_settings();
		}

		$site = self::get_site_settings();

		if ( ! NetworkScope::isNetworkActivated() ) {
			return $site;
		}

		$network = self::get_network_settings();

		if ( ! empty( $network['network_force_enabled'] ) ) {
			return array_merge( $site, $network );
		}

		if ( ! empty( $site['use_network_default'] ) && ! empty( $network['network_default_enabled'] ) ) {
			return array_merge( $site, $network );
		}

		return $site;
	}

	/**
	 * @return 'site'|'network'|'network_forced'
	 */
	public static function get_settings_source_label(): string {
		if ( ! NetworkScope::isNetworkActivated() ) {
			return 'site';
		}

		$site    = self::get_site_settings();
		$network = self::get_network_settings();

		if ( ! empty( $network['network_force_enabled'] ) ) {
			return 'network_forced';
		}

		if ( ! empty( $site['use_network_default'] ) && ! empty( $network['network_default_enabled'] ) ) {
			return 'network';
		}

		return 'site';
	}

	public static function can_manage_network_settings(): bool {
		return NetworkScope::isNetworkActivated() && current_user_can( 'manage_network_options' );
	}

	/**
	 * @param array<string, mixed> $settings Raw settings.
	 * @param string               $context  site|network|import|save
	 * @return array<string, mixed>
	 */
	public static function sanitize( array $settings, string $context = 'save' ): array {
		$defaults = self::get_default_settings();

		$mode = isset( $settings['mode'] ) ? sanitize_key( (string) $settings['mode'] ) : $defaults['mode'];
		if ( ! in_array( $mode, self::MODES, true ) ) {
			$mode = 'disabled';
		}

		$scope = isset( $settings['scope'] ) ? sanitize_key( (string) $settings['scope'] ) : $defaults['scope'];
		if ( ! in_array( $scope, self::SCOPES, true ) ) {
			$scope = 'admin_only';
		}

		$registry = Scheme_Registry::instance();

		$custom_schemes = [];
		if ( FeatureGate::isPremiumLicensed() && class_exists( Premium::class, false ) ) {
			$custom_schemes = Premium::sanitize_custom_schemes( $settings['custom_schemes'] ?? [], $context );
		}

		$temp_for_ids = array_merge( $defaults, [ 'custom_schemes' => $custom_schemes ] );
		$all_schemes  = $registry->get_all_scheme_ids( $temp_for_ids );

		$active_scheme = isset( $settings['active_scheme'] ) ? sanitize_key( (string) $settings['active_scheme'] ) : $defaults['active_scheme'];
		if ( ! in_array( $active_scheme, $all_schemes, true ) ) {
			$active_scheme = 'powersuite_blue';
		}

		$role_schemes = [];
		if ( FeatureGate::isPremiumLicensed() && class_exists( Premium::class, false ) ) {
			$role_schemes = Premium::sanitize_role_schemes( $settings['role_schemes'] ?? [], $all_schemes );
		}

		$env = is_array( $settings['environment_badge'] ?? null ) ? $settings['environment_badge'] : [];
		$env_type = isset( $env['type'] ) ? sanitize_key( (string) $env['type'] ) : 'production';
		if ( ! in_array( $env_type, [ 'disabled', 'staging', 'development', 'production', 'custom' ], true ) ) {
			$env_type = 'production';
		}

		$env_color = Scheme_Registry::sanitize_hex_color( $env['color'] ?? '#cc0000' ) ?? '#cc0000';

		$allow_custom_css = ! empty( $settings['allow_custom_css'] );
		$custom_css       = '';
		if ( $allow_custom_css && isset( $settings['custom_css'] ) && is_string( $settings['custom_css'] ) ) {
			$custom_css = self::sanitize_custom_css( $settings['custom_css'] );
		}

		$network_default_enabled = ! empty( $settings['network_default_enabled'] );
		$network_force_enabled   = ! empty( $settings['network_force_enabled'] );

		if ( $context === 'site' || ( $context === 'save' && ! self::can_manage_network_settings() ) ) {
			$network_default_enabled = false;
			$network_force_enabled   = false;
		}

		$enabled = $mode !== 'disabled';

		$sanitized = [
			'enabled'                 => $enabled,
			'mode'                    => $mode,
			'scope'                   => $scope,
			'active_scheme'           => $active_scheme,
			'force_scheme'            => in_array( $mode, [ 'force_all', 'force_by_role' ], true ),
			'role_schemes'            => $role_schemes,
			'custom_schemes'          => $custom_schemes,
			'allow_custom_css'        => $allow_custom_css,
			'custom_css'              => $custom_css,
			'environment_badge'       => [
				'enabled'         => ! empty( $env['enabled'] ) && $env_type !== 'disabled',
				'type'            => $env_type,
				'label'           => sanitize_text_field( (string) ( $env['label'] ?? '' ) ),
				'color'           => $env_color,
				'apply_bar_color' => ! empty( $env['apply_bar_color'] ),
			],
			'frontend_admin_bar'      => $scope === 'admin_and_admin_bar',
			'login_screen'            => false,
			'version'                 => self::VERSION,
			'use_network_default'     => ! empty( $settings['use_network_default'] ),
			'network_default_enabled' => $network_default_enabled,
			'network_force_enabled'   => $network_force_enabled,
		];

		return FeatureGate::applyPremiumTierLimits( $sanitized );
	}

	public static function sanitize_custom_css( string $css ): string {
		$css = wp_strip_all_tags( $css );
		$css = preg_replace( '/@import\b[^;]*;?/i', '', $css ) ?? '';
		$css = preg_replace( '/expression\s*\(/i', '', $css ) ?? '';
		$css = preg_replace( '/javascript\s*:/i', '', $css ) ?? '';
		$css = preg_replace( '/behavior\s*:/i', '', $css ) ?? '';
		$css = preg_replace( '/-moz-binding\s*:/i', '', $css ) ?? '';
		$css = substr( $css, 0, 50000 );

		return trim( $css );
	}

	/**
	 * @param array<string, mixed> $settings
	 */
	public static function save_site_settings( array $settings ): bool {
		$sanitized = self::sanitize( $settings, 'site' );
		return OptionStoreModuleSettingsRepository::forModule( self::MODULE_ID )->save( $sanitized );
	}

	/**
	 * @param array<string, mixed> $settings
	 */
	public static function save_network_settings( array $settings ): bool {
		if ( ! self::can_manage_network_settings() ) {
			return false;
		}

		$sanitized = self::sanitize( $settings, 'network' );
		$all       = NetworkScope::getPluginOption( 'wp_powersuite_settings', [] );
		if ( ! is_array( $all ) ) {
			$all = [];
		}
		$all[ self::MODULE_ID ] = $sanitized;

		return NetworkScope::updatePluginOption( 'wp_powersuite_settings', $all );
	}

	/**
	 * @return array<string, mixed>
	 */
	public static function get_accessible_defaults(): array {
		return [
			'primary'             => '#2271b1',
			'secondary'           => '#135e96',
			'accent'              => '#72aee6',
			'menu_bg'             => '#1d2327',
			'menu_text'           => '#f0f0f1',
			'menu_icon'           => '#72aee6',
			'menu_hover_bg'       => '#2271b1',
			'menu_hover_text'     => '#ffffff',
			'menu_hover_icon'     => '#ffffff',
			'menu_current_bg'     => '#2271b1',
			'menu_current_text'   => '#ffffff',
			'menu_current_icon'   => '#ffffff',
			'toolbar_bg'          => '#1d2327',
			'toolbar_text'        => '#f0f0f1',
			'adminbar_icon'       => '#72aee6',
			'button_bg'           => '#2271b1',
			'button_text'         => '#ffffff',
			'button_border'       => '#135e96',
			'button_hover_bg'     => '#135e96',
			'button_hover_text'   => '#ffffff',
			'button_hover_border' => '#135e96',
			'notice'              => '#72aee6',
		];
	}
}
