<?php
/**
 * This file contains the class that defines REST API endpoints for templates.
 *
 * @package    Nelio_AB_Testing
 * @subpackage Nelio_AB_Testing/includes/rest
 * @since      5.0.0
 */

defined( 'ABSPATH' ) || exit;

class Nelio_AB_Testing_Template_REST_Controller extends WP_REST_Controller {

	/**
	 * Hooks into WordPress.
	 *
	 * @return void
	 * @since  5.0.0
	 */
	public function init() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register the routes for the objects of the controller.
	 *
	 * @return void
	 */
	public function register_routes() {
		register_rest_route(
			nelioab()->rest_namespace,
			'/template-contexts',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_template_contexts' ),
					'permission_callback' => nab_capability_checker( 'edit_nab_experiments' ),
				),
			)
		);

		register_rest_route(
			nelioab()->rest_namespace,
			'/templates',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_templates' ),
					'permission_callback' => nab_capability_checker( 'edit_nab_experiments' ),
				),
			)
		);
	}

	/**
	 * Returns all templates.
	 *
	 * @return array{results:array<string,TTemplate_Context_Group>,pagination:array{more:false,pages:1}}
	 */
	public function get_template_contexts() {
		$post_types = get_post_types(
			array(
				'public'   => true,
				'_builtin' => false,
			),
			'objects'
		);

		$page = get_post_type_object( 'page' );
		$post = get_post_type_object( 'post' );
		if ( isset( $page ) ) {
			$post_types['page'] = $page;
		}
		if ( isset( $post ) ) {
			$post_types['post'] = $post;
		}

		$contexts = array_map(
			function ( $post_type ) {
				return array(
					'name'  => $post_type->name,
					'label' => $post_type->label,
				);
			},
			$post_types
		);

		$result = array(
			'wp' => array(
				'label'    => _x( 'WordPress', 'text', 'nelio-ab-testing' ),
				'contexts' => $contexts,
			),
		);

		/**
		 * Filters the array of template contexts available in a Nelio A/B Testing’s REST request.
		 *
		 * @param array<string,TTemplate_Context_Group> $template_contexts The template contexts.
		 *
		 * @since 6.7.0
		 */
		$result = apply_filters( 'nab_template_contexts', $result );

		return array(
			'results'    => $result,
			'pagination' => array(
				'more'  => false,
				'pages' => 1,
			),
		);
	}

	/**
	 * Returns all templates.
	 *
	 * @return array{results:array<string,list<TTemplate>>,pagination:array{more:false,pages:1}}
	 */
	public function get_templates() {
		$args = array(
			'public'   => true,
			'_builtin' => false,
		);

		$post_types = get_post_types( $args, 'names', 'and' );
		$post_types = array_unique( array_merge( $post_types, array( 'page', 'post' ) ) );

		$result = array();
		foreach ( $post_types as $post_type ) {
			$result[ "wp:{$post_type}" ] = $this->get_templates_in_post_type( $post_type );
		}

		/**
		 * Filters the array of templates available for each post type in a Nelio A/B Testing’s REST request.
		 *
		 * @param array<string,list<TTemplate>> $templates The templates for each post type.
		 *
		 * @since 6.7.0
		 */
		$result = apply_filters( 'nab_templates', $result );

		return array(
			'results'    => $result,
			'pagination' => array(
				'more'  => false,
				'pages' => 1,
			),
		);
	}

	/**
	 * Returns avilable templates for the given post type.
	 *
	 * @param string $post_type Post type.
	 *
	 * @return list<TTemplate>
	 */
	private function get_templates_in_post_type( $post_type ) {

		$templates = wp_get_theme()->get_page_templates( null, $post_type );
		$templates = array_map(
			function ( $id, $name ) {
				return array(
					'id'   => $id,
					'name' => $name,
				);
			},
			array_keys( $templates ),
			array_values( $templates )
		);

		$has_front_page_template = ! empty( locate_template( 'front-page.php' ) );
		if ( 'page' === $post_type && $has_front_page_template ) {
			$templates[] = array(
				'id'   => '_nab_front_page_template',
				'name' => sprintf(
					/* translators: %s: Template name. */
					_x( 'Front Page template (%s)', 'text', 'nelio-ab-testing' ),
					'front-page.php'
				),
			);
		}

		usort( $templates, fn ( $a, $b ) => strcasecmp( $a['name'], $b['name'] ) );

		if ( count( $templates ) ) {
			$templates = array_merge(
				array(
					array(
						'id'   => '_nab_default_template',
						'name' => _x( 'Default template', 'text', 'nelio-ab-testing' ),
					),
				),
				$templates
			);
		}

		return $templates;
	}
}
