<?php

namespace EaLab\WP_Deployer\includes\Rest;

use Exception;

/**
 * Base class for Rest functionality.
 */
class RestBase {
	/**
	 * Gets the register_rest_route args to use when registering.
	 *
	 * @return array<array<string,mixed>> The array of arrays of register_rest_route args.
	 */
	static public function getRegisterRestRouteDefinitions(): array {
		// Implement this.
		return [];
	}

	/**
	 * Registers the REST hooks.
	 */
	static public function registerRestHooks(): void {
		foreach (static::getRegisterRestRouteDefinitions() ?? array() as $rest_hook_definition) {
			if (empty($rest_hook_definition['route'])) {
				continue;
			}

			static::validateRestRouteDefinition($rest_hook_definition);

			add_action(
				'rest_api_init',
				static function () use ($rest_hook_definition) {
					register_rest_route(
						$rest_hook_definition['route_namespace'] ?? 'deploy-sync-content/v1',
						$rest_hook_definition['route'],
						$rest_hook_definition['args'] ?? array(),
						$rest_hook_definition['override'] ?? false,
					);
				}
			);
		}
	}

	/**
	 * Validates the REST route definition to ensure it has a permission_callback.
	 *
	 * @param array $rest_hook_definition The REST route definition to validate.
	 *
	 * @throws Exception If the route definition is invalid.
	 */
	static protected function validateRestRouteDefinition(array $rest_hook_definition): void {
		if (empty($rest_hook_definition['args'])) {
			throw new Exception(esc_html__('REST route definition must include args array', 'deploy-sync-content'));
		}

		// Handle both single method and multiple methods definitions.
		$args_to_check = isset($rest_hook_definition['args']['methods'])
			? [$rest_hook_definition['args']]
			: $rest_hook_definition['args'];

		foreach ($args_to_check as $method => $args) {
			if (!isset($args['permission_callback'])) {
				throw new Exception(sprintf(
					                    esc_html__('REST route %s for method %s must include a permission_callback', 'deploy-sync-content'),
					                    esc_html($rest_hook_definition['route']),
					                    esc_html(is_string($method) ? $method : 'default')
				                    ));
			}
		}
	}
}
