<?php
/**
 * REST API controller.
 *
 * @package BatoCookieConsent
 */

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

final class Bato_Cookie_Consent_REST_Controller
{
    private Bato_Cookie_Consent_Settings $settings;

    public function __construct(Bato_Cookie_Consent_Settings $settings)
    {
        $this->settings = $settings;
    }

    public function init(): void
    {
        add_action('rest_api_init', array($this, 'register_routes'));
    }

    public function register_routes(): void
    {
        register_rest_route(
            'bato-cookie-consent/v1',
            '/settings',
            array(
                array(
                    'methods' => WP_REST_Server::READABLE,
                    'callback' => array($this, 'get_settings'),
                    'permission_callback' => array($this, 'can_manage'),
                ),
                array(
                    'methods' => WP_REST_Server::CREATABLE,
                    'callback' => array($this, 'save_settings'),
                    'permission_callback' => array($this, 'can_manage'),
                ),
            )
        );

        register_rest_route(
            'bato-cookie-consent/v1',
            '/pages',
            array(
                'methods' => WP_REST_Server::READABLE,
                'callback' => array($this, 'search_pages'),
                'permission_callback' => array($this, 'can_manage'),
                'args' => array(
                    'search' => array(
                        'type' => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                        'default' => '',
                    ),
                ),
            )
        );
    }

    public function can_manage(): bool
    {
        return current_user_can('manage_options');
    }

    public function get_settings(): WP_REST_Response
    {
        return rest_ensure_response(
            array(
                'settings' => $this->settings->get(),
                'defaults' => Bato_Cookie_Consent_Settings::defaults(),
                'meta' => $this->settings->metadata(),
            )
        );
    }

    public function save_settings(WP_REST_Request $request)
    {
        $nonce = $request->get_header('x_wp_nonce');

        if (! $nonce || ! wp_verify_nonce($nonce, 'wp_rest')) {
            return new WP_Error(
                'bato_cookie_consent_invalid_nonce',
                __('Invalid security token.', 'bato-cookie-consent'),
                array('status' => 403)
            );
        }

        $payload = $request->get_json_params();

        if (! is_array($payload)) {
            return new WP_Error(
                'bato_cookie_consent_invalid_payload',
                __('Invalid settings payload.', 'bato-cookie-consent'),
                array('status' => 400)
            );
        }

        return rest_ensure_response(
            array(
                'settings' => $this->settings->save($payload),
                'meta' => $this->settings->metadata(),
            )
        );
    }

    public function search_pages(WP_REST_Request $request): WP_REST_Response
    {
        $query = new WP_Query(
            array(
                'post_type' => 'page',
                'post_status' => array('publish', 'draft', 'private'),
                's' => sanitize_text_field((string) $request->get_param('search')),
                'posts_per_page' => 20,
                'orderby' => 'title',
                'order' => 'ASC',
                'no_found_rows' => true,
            )
        );

        $pages = array_map(
            static function (WP_Post $page): array {
                return array(
                    'id' => $page->ID,
                    'title' => html_entity_decode(get_the_title($page), ENT_QUOTES, get_bloginfo('charset')),
                    'url' => get_permalink($page),
                    'status' => get_post_status($page),
                );
            },
            $query->posts
        );

        return rest_ensure_response($pages);
    }
}
