<?php
/**
 * REST API handler for Jetix Store Toolkit for WooCommerce dashboard.
 *
 * @package JWP_STK
 */

namespace JWP_STK\Admin;

use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use JWP_STK\Options;
use JWP_STK\Module_Manager;
use JWP_STK\Compatibility\Theme_Provider;

defined( 'ABSPATH' ) || exit;

/**
 * REST_API class.
 */
class REST_API {

	/**
	 * API Namespace.
	 *
	 * @var string
	 */
	const API_NAMESPACE = 'jwp-stk/v1';

	/**
	 * Class instance.
	 *
	 * @var REST_API
	 */
	protected static $instance;

	/**
	 * Get class instance.
	 *
	 * @return REST_API
	 */
	public static function get_instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register REST API routes.
	 *
	 * @return void
	 */
	public function register_routes() {
		// Get all modules with their active state.
		register_rest_route(
			self::API_NAMESPACE,
			'/modules',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_modules' ),
				'permission_callback' => array( $this, 'check_permission' ),
			)
		);

		// Toggle module activation.
		register_rest_route(
			self::API_NAMESPACE,
			'/modules/toggle',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'toggle_module' ),
				'permission_callback' => array( $this, 'check_permission' ),
				'args'                => array(
					'module' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
					'active' => array(
						'required' => true,
						'type'     => 'boolean',
					),
				),
			)
		);

		// Get settings.
		register_rest_route(
			self::API_NAMESPACE,
			'/settings',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_settings' ),
				'permission_callback' => array( $this, 'check_permission' ),
			)
		);

		// Save settings.
		register_rest_route(
			self::API_NAMESPACE,
			'/settings',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'save_settings' ),
				'permission_callback' => array( $this, 'check_permission' ),
				'args'                => array(
					'settings' => array(
						'required' => true,
						'type'     => 'object',
					),
				),
			)
		);

		// Get module-specific settings.
		register_rest_route(
			self::API_NAMESPACE,
			'/modules/(?P<slug>[a-z0-9-]+)/settings',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_module_settings' ),
				'permission_callback' => array( $this, 'check_permission' ),
				'args'                => array(
					'slug' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
				),
			)
		);

		// Save module-specific settings.
		register_rest_route(
			self::API_NAMESPACE,
			'/modules/(?P<slug>[a-z0-9-]+)/settings',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'save_module_settings' ),
				'permission_callback' => array( $this, 'check_permission' ),
				'args'                => array(
					'slug'     => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
					'settings' => array(
						'required' => true,
						'type'     => 'object',
					),
				),
			)
		);

		// Get all blocks with their active state.
		register_rest_route(
			self::API_NAMESPACE,
			'/blocks',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_blocks' ),
				'permission_callback' => array( $this, 'check_permission' ),
			)
		);

		// Toggle block activation.
		register_rest_route(
			self::API_NAMESPACE,
			'/blocks/toggle',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'toggle_block' ),
				'permission_callback' => array( $this, 'check_permission' ),
				'args'                => array(
					'block'  => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
					'active' => array(
						'required' => true,
						'type'     => 'boolean',
					),
				),
			)
		);

		/**
		 * Fires after Jetix Store Toolkit for WooCommerce REST routes are registered.
		 *
		 * @param string $namespace API namespace.
		 */
		do_action( 'jwp_stk_register_rest_routes', self::API_NAMESPACE );
	}

	/**
	 * Permission check for REST requests.
	 *
	 * @return bool|WP_Error
	 */
	public function check_permission() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return new WP_Error(
				'jwp_stk_rest_forbidden',
				__( 'You do not have permission to access this resource.', 'jetix-store-toolkit' ),
				array( 'status' => 403 )
			);
		}
		return true;
	}

	/**
	 * Get all modules.
	 *
	 * @return WP_REST_Response
	 */
	public function get_modules() {
		$module_manager = Module_Manager::get_instance();
		$modules        = $module_manager->get_modules();
		$active_modules = $module_manager->get_active_modules();

		$response = array();

		foreach ( $modules as $slug => $module ) {
			$response[] = array(
				'slug'        => $slug,
				'title'       => $module['title'],
				'description' => $module['description'],
				'tier'        => $module['tier'],
				'enabled'     => ! empty( $module['enabled'] ),
				'active'      => in_array( $slug, $active_modules, true ),
			);
		}

		return new WP_REST_Response( $response, 200 );
	}

	/**
	 * Toggle module activation.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function toggle_module( WP_REST_Request $request ) {
		$module_slug = $request->get_param( 'module' );
		$active      = $request->get_param( 'active' );

		$module_manager = Module_Manager::get_instance();
		$modules        = $module_manager->get_modules();

		if ( ! isset( $modules[ $module_slug ] ) ) {
			return new WP_Error(
				'jwp_stk_invalid_module',
				__( 'Invalid module.', 'jetix-store-toolkit' ),
				array( 'status' => 400 )
			);
		}

		if ( empty( $modules[ $module_slug ]['enabled'] ) ) {
			return new WP_Error(
				'jwp_stk_module_not_available',
				__( 'This module is not available for activation.', 'jetix-store-toolkit' ),
				array( 'status' => 400 )
			);
		}

		if ( $active ) {
			$module_manager->activate_module( $module_slug );
		} else {
			$module_manager->deactivate_module( $module_slug );
		}

		return new WP_REST_Response(
			array(
				'success' => true,
				'module'  => $module_slug,
				'active'  => $active,
			),
			200
		);
	}

	/**
	 * Get settings.
	 *
	 * @return WP_REST_Response
	 */
	public function get_settings() {
		$options        = Options::get_instance();
		$theme_provider = Theme_Provider::get_instance();

		$settings = array(
			'theme_compatibility_engine' => $options->get( 'theme-compatibility-engine', 'auto' ),
			'available_theme_engines'    => $theme_provider->get_selectable_engine_options(),
			'active_theme_engine'        => $options->get( 'active-theme-engine', '' ),
			'automatic_theme_engine'     => $options->get( 'automatic-theme-engine', '' ),
			'color_palette'              => $options->get( 'color-palette', null ),
		);

		/**
		 * Filter settings returned via REST API.
		 *
		 * @param array $settings Settings data.
		 */
		$settings = apply_filters( 'jwp_stk_rest_settings', $settings );

		return new WP_REST_Response( $settings, 200 );
	}

	/**
	 * Save settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function save_settings( WP_REST_Request $request ) {
		$settings = $request->get_param( 'settings' );
		$options  = Options::get_instance();

		// Allowlist of saveable settings.
		$allowed_keys = array(
			'theme-compatibility-engine',
			'color-palette',
		);

		/**
		 * Filter allowed setting keys.
		 *
		 * @param array $allowed_keys Allowed setting keys.
		 */
		$allowed_keys = apply_filters( 'jwp_stk_allowed_settings_keys', $allowed_keys );

		// Handle color palette (array) separately — sanitize each hex value.
		if ( isset( $settings['color-palette'] ) && is_array( $settings['color-palette'] ) ) {
			$sanitized_palette = array_values(
				array_filter(
					array_map( 'sanitize_hex_color', $settings['color-palette'] ),
					function ( $c ) {
						return ! empty( $c ); }
				)
			);
			$options->set( 'color-palette', $sanitized_palette );
			unset( $settings['color-palette'] );
		}

		foreach ( $settings as $key => $value ) {
			if ( in_array( $key, $allowed_keys, true ) ) {
				$options->set( sanitize_text_field( $key ), sanitize_text_field( $value ) );
			}
		}

		return new WP_REST_Response(
			array(
				'success' => true,
			),
			200
		);
	}

	/**
	 * Get module-specific settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function get_module_settings( WP_REST_Request $request ) {
		$slug   = $request->get_param( 'slug' );
		$plugin = \JWP_STK\Plugin::get_instance();
		$module = $plugin->get_module( $slug );

		if ( ! $module ) {
			// Module not active, return defaults from class file if available.
			$module = $this->load_module_class( $slug );

			if ( ! $module ) {
				return new WP_Error(
					'jwp_stk_module_not_found',
					__( 'Module not found.', 'jetix-store-toolkit' ),
					array( 'status' => 404 )
				);
			}
		}

		return new WP_REST_Response( $module->get_settings_schema(), 200 );
	}

	/**
	 * Save module-specific settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function save_module_settings( WP_REST_Request $request ) {
		$slug     = $request->get_param( 'slug' );
		$settings = $request->get_param( 'settings' );
		$plugin   = \JWP_STK\Plugin::get_instance();
		$module   = $plugin->get_module( $slug );

		if ( ! $module ) {
			$module = $this->load_module_class( $slug );

			if ( ! $module ) {
				return new WP_Error(
					'jwp_stk_module_not_found',
					__( 'Module not found.', 'jetix-store-toolkit' ),
					array( 'status' => 404 )
				);
			}
		}

		$saved = $module->save_settings( $settings );

		return new WP_REST_Response(
			array(
				'success'  => true,
				'settings' => $saved,
			),
			200
		);
	}

	/**
	 * Attempt to load a module class for settings access.
	 *
	 * @param string $slug Module slug.
	 * @return \JWP_STK\Modules\Base_Module|null
	 */
	private function load_module_class( $slug ) {
		$map = array(
			'quick-view'            => 'QuickView',
			'custom-order-statuses' => 'CustomOrderStatuses',
			'stock-manager'         => 'StockManager',
			'product-tab-manager'   => 'ProductTabManager',
			'wishlist'              => 'Wishlist',
			'social-sharing'        => 'SocialSharing',
		);

		if ( ! isset( $map[ $slug ] ) ) {
			return null;
		}

		$dir_name   = $map[ $slug ];
		$class_file = JWP_STK_PLUGIN_DIR . 'includes/Modules/' . $dir_name . '/class-module.php';

		if ( ! file_exists( $class_file ) ) {
			return null;
		}

		require_once $class_file;

		$class_name = '\\JWP_STK\\Modules\\' . $dir_name . '\\Module';

		if ( ! class_exists( $class_name ) ) {
			return null;
		}

		return new $class_name();
	}

	/**
	 * Get all blocks with their active state.
	 *
	 * @return WP_REST_Response
	 */
	public function get_blocks() {
		$registry = \JWP_STK\Blocks\Blocks_Registry::get_instance();
		$blocks   = $registry->get_blocks();

		// Strip internal 'dir' key from the response.
		$response = array_map(
			function ( $block ) {
				return array(
					'slug'        => $block['slug'],
					'name'        => $block['name'],
					'description' => $block['description'],
					'active'      => $block['active'],
				);
			},
			$blocks
		);

		return new WP_REST_Response( array_values( $response ), 200 );
	}

	/**
	 * Toggle block activation.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function toggle_block( WP_REST_Request $request ) {
		$block_slug = $request->get_param( 'block' );
		$active     = $request->get_param( 'active' );

		$registry = \JWP_STK\Blocks\Blocks_Registry::get_instance();
		$success  = $registry->toggle_block( $block_slug, $active );

		if ( ! $success ) {
			return new WP_Error(
				'jwp_stk_invalid_block',
				__( 'Invalid block slug.', 'jetix-store-toolkit' ),
				array( 'status' => 400 )
			);
		}

		return new WP_REST_Response(
			array(
				'success' => true,
				'block'   => $block_slug,
				'active'  => $active,
			),
			200
		);
	}
}
