<?php
/**
 * Plugin settings storage.
 *
 * @package Rsmspark_Content_Widgets
 */

defined( 'ABSPATH' ) || exit;

/**
 * Rsmspark_Content_Widgets_Settings
 */
class Rsmspark_Content_Widgets_Settings {

	const OPTION_KEY = 'rsmspark_content_widgets_settings';

	/**
	 * @return array<string, mixed>
	 */
	public static function defaults() {
		return array(
			'enabled'            => true,
			'load_assets'        => 'conditional',
			'primary_color'      => '#2563eb',
			'border_radius'      => '8',
			'widgets_enabled'    => Rsmspark_Content_Widgets_Registry::default_enabled_map(),
			'output_shortcodes'  => true,
			'output_blocks'      => true,
			'output_siteorigin'  => true,
			'license_key'        => '',
			'license_server_url' => '',
			'debug_mode'              => false,
			'per_widget_assets'       => false,
			'disable_all_styling'     => false,
			'experimental_blocks'     => false,
			'legacy_shortcode_support' => false,
			'editor_media_row'         => false,
			'editor_use_rsm_media'     => true,
			'editor_calendar_button'   => false,
		);
	}

	/**
	 * @return array<string, mixed>
	 */
	public static function get() {
		$stored = get_option( self::OPTION_KEY, array() );
		if ( ! is_array( $stored ) ) {
			$stored = array();
		}

		$merged = wp_parse_args( $stored, self::defaults() );

		$widget_defaults = Rsmspark_Content_Widgets_Registry::default_enabled_map();
		$enabled         = is_array( $merged['widgets_enabled'] ?? null ) ? $merged['widgets_enabled'] : array();
		foreach ( $widget_defaults as $id => $default_on ) {
			if ( ! array_key_exists( $id, $enabled ) ) {
				$enabled[ $id ] = $default_on;
			} else {
				$enabled[ $id ] = (bool) $enabled[ $id ];
			}
		}
		$merged['widgets_enabled'] = $enabled;

		$merged['output_shortcodes'] = ! empty( $merged['output_shortcodes'] );
		$merged['output_blocks']     = ! empty( $merged['output_blocks'] );
		$merged['output_siteorigin'] = ! empty( $merged['output_siteorigin'] );

		return $merged;
	}

	/**
	 * @return void
	 */
	public static function ensure_defaults() {
		if ( false === get_option( self::OPTION_KEY, false ) ) {
			self::save( self::defaults() );
		}
	}

	/**
	 * @return bool
	 */
	public static function is_enabled() {
		$settings = self::get();
		return ! empty( $settings['enabled'] );
	}

	/**
	 * @param string $widget_id Widget id.
	 * @return bool
	 */
	public static function is_widget_enabled( $widget_id ) {
		$settings = self::get();
		$id       = sanitize_key( (string) $widget_id );
		$map      = is_array( $settings['widgets_enabled'] ?? null ) ? $settings['widgets_enabled'] : array();
		return ! empty( $map[ $id ] );
	}

	/**
	 * @return bool
	 */
	public static function shortcodes_enabled() {
		$settings = self::get();
		return self::is_enabled() && ! empty( $settings['output_shortcodes'] );
	}

	/**
	 * @return bool
	 */
	public static function blocks_enabled() {
		$settings = self::get();
		return self::is_enabled() && ! empty( $settings['output_blocks'] );
	}

	/**
	 * Load native block editor UI (includes SOWB → native bridges for widget-area legacy blocks).
	 *
	 * @return bool
	 */
	public static function block_editor_ui_enabled() {
		if ( ! self::is_enabled() ) {
			return false;
		}

		if ( self::blocks_enabled() ) {
			return true;
		}

		if ( self::siteorigin_enabled() && class_exists( 'SiteOrigin_Widget', false ) ) {
			return true;
		}

		// Block types still register server-side for the front end when output_blocks is off.
		// Without editor scripts the block editor shows "Unsupported block" on imported markup.
		return class_exists( 'Rsmspark_Content_Widgets_Blocks', false )
			&& Rsmspark_Content_Widgets_Blocks::has_block_definitions();
	}

	/**
	 * @return bool
	 */
	public static function siteorigin_enabled() {
		$settings = self::get();
		return self::is_enabled() && ! empty( $settings['output_siteorigin'] );
	}

	/**
	 * Show rsmspark-cw-compat/* aliases in the block inserter (hidden by default).
	 *
	 * @return bool
	 */
	public static function experimental_blocks_enabled() {
		$settings = self::get();
		return ! empty( $settings['experimental_blocks'] );
	}

	/**
	 * Show the media-buttons row above RSM profile TinyMCE fields.
	 *
	 * @return bool
	 */
	public static function editor_media_row_enabled() {
		$settings = self::get();
		return ! empty( $settings['editor_media_row'] );
	}

	/**
	 * Use RSM Media picker instead of core Add Media on profile editors.
	 *
	 * @return bool
	 */
	public static function editor_use_rsm_media_picker() {
		$settings = self::get();
		return ! empty( $settings['editor_use_rsm_media'] );
	}

	/**
	 * Allow Add RSM Calendar in the profile editor media row (requires Calendar plugin).
	 *
	 * @return bool
	 */
	public static function editor_calendar_button_enabled() {
		$settings = self::get();
		return ! empty( $settings['editor_calendar_button'] );
	}

	/**
	 * Persist newly added registry widgets (default_on) into stored settings.
	 *
	 * @return bool True when settings were updated.
	 */
	public static function merge_registry_widgets() {
		$stored = get_option( self::OPTION_KEY, array() );
		if ( ! is_array( $stored ) ) {
			$stored = array();
		}

		$widget_defaults = Rsmspark_Content_Widgets_Registry::default_enabled_map();
		$enabled         = is_array( $stored['widgets_enabled'] ?? null ) ? $stored['widgets_enabled'] : array();
		$changed         = false;

		foreach ( $widget_defaults as $id => $default_on ) {
			if ( ! array_key_exists( $id, $enabled ) ) {
				$enabled[ $id ] = (bool) $default_on;
				$changed        = true;
			}
		}

		if ( ! $changed ) {
			return false;
		}

		$stored['widgets_enabled'] = $enabled;
		self::save( wp_parse_args( $stored, self::defaults() ) );

		return true;
	}

	/**
	 * @param array<string, mixed> $input Raw input.
	 * @return void
	 */
	public static function save( array $input ) {
		update_option( self::OPTION_KEY, self::sanitize( $input ), false );
	}

	/**
	 * @param array<string, mixed> $input Raw input.
	 * @return array<string, mixed>
	 */
	public static function sanitize( array $input ) {
		$defaults = self::defaults();
		$clean    = wp_parse_args( $input, $defaults );

		$clean['enabled']           = ! empty( $clean['enabled'] );
		$clean['debug_mode']              = ! empty( $clean['debug_mode'] );
		$clean['per_widget_assets']       = ! empty( $clean['per_widget_assets'] );
		$clean['disable_all_styling']     = ! empty( $clean['disable_all_styling'] );
		$clean['experimental_blocks']     = ! empty( $clean['experimental_blocks'] );
		$clean['legacy_shortcode_support'] = ! empty( $clean['legacy_shortcode_support'] );
		$clean['editor_media_row']         = ! empty( $clean['editor_media_row'] );
		$clean['editor_use_rsm_media']     = ! empty( $clean['editor_use_rsm_media'] );
		$clean['editor_calendar_button']   = ! empty( $clean['editor_calendar_button'] );
		$clean['output_shortcodes'] = ! empty( $clean['output_shortcodes'] );
		$clean['output_blocks']     = ! empty( $clean['output_blocks'] );
		$clean['output_siteorigin'] = ! empty( $clean['output_siteorigin'] );
		$clean['primary_color']     = sanitize_hex_color( (string) ( $clean['primary_color'] ?? '#2563eb' ) ) ?: '#2563eb';
		$clean['border_radius']     = max( 0, absint( $clean['border_radius'] ?? 8 ) );

		$load = sanitize_key( (string) ( $clean['load_assets'] ?? 'conditional' ) );
		$clean['load_assets'] = in_array( $load, array( 'always', 'conditional', 'never' ), true ) ? $load : 'conditional';

		$clean['license_key']        = strtoupper( preg_replace( '/[^A-Z0-9\-]/', '', (string) ( $clean['license_key'] ?? '' ) ) );
		$clean['license_server_url'] = untrailingslashit( esc_url_raw( (string) ( $clean['license_server_url'] ?? '' ) ) );

		$widget_defaults = Rsmspark_Content_Widgets_Registry::default_enabled_map();
		$raw_widgets     = is_array( $clean['widgets_enabled'] ?? null ) ? $clean['widgets_enabled'] : array();
		$widgets         = array();
		foreach ( $widget_defaults as $id => $default_on ) {
			if ( array_key_exists( $id, $raw_widgets ) ) {
				$widgets[ $id ] = ! empty( $raw_widgets[ $id ] );
			} else {
				$widgets[ $id ] = (bool) $default_on;
			}
		}
		$clean['widgets_enabled'] = $widgets;

		return $clean;
	}
}
