<?php

/**
 * REST API Handler
 *
 * @package _121Digital\Connect
 */

namespace _121Digital\Connect\API;

use _121Digital\Connect\Security\KeyManager;
use WP_REST_Request;
use WP_REST_Response;

/**
 * REST API Class
 *
 * Handles all REST API endpoints for the plugin
 */
class RestApi
{
    /**
     * Register REST API routes
     *
     * @return void
     */
    public function register(): void
    {
        add_action('rest_api_init', [$this, 'registerRoutes']);
        add_action('login_init', [$this, 'handleTokenLogin']);
    }

    /**
     * Register all REST API routes
     *
     * @return void
     */
    public function registerRoutes(): void
    {
        register_rest_route('sc/v1', '/ping', [
            'methods' => 'POST',
            'callback' => [$this, 'handlePing'],
            'permission_callback' => '__return_true',
        ]);

        register_rest_route('sc/v1', '/example-data', [
            'methods' => 'POST',
            'callback' => [$this, 'handleExampleData'],
            'permission_callback' => '__return_true',
        ]);

        register_rest_route('sc/v1', '/verify-registration', [
            'methods' => 'POST',
            'callback' => [$this, 'handleVerifyRegistration'],
            'permission_callback' => '__return_true',
        ]);

        register_rest_route('sc/v1', '/execute-command', [
            'methods' => 'POST',
            'callback' => [$this, 'handleExecuteCommand'],
            'permission_callback' => '__return_true',
        ]);
    }

    /**
     * Handle token-based login
     *
     * @return void
     */
    public function handleTokenLogin(): void
    {
        if ($_POST && isset($_POST['payload'])) {
            $payload = $_POST['payload'];
            $keyManager = new KeyManager();
            $decryptedRedirectUrl = $keyManager->decrypt($payload);
            wp_redirect($decryptedRedirectUrl);
            exit;
        }

        if (!isset($_GET['asc']) || !isset($_GET['ast'])) {
            return;
        }

        $sessionCode = sanitize_text_field($_GET['asc']);
        $token = sanitize_text_field($_GET['ast']);

        $storedToken = get_option("sc_login_{$sessionCode}_token");
        $storedUser = get_option("sc_login_{$sessionCode}_username");

        if (!$storedToken || !$storedUser || $token !== $storedToken) {
            wp_die('Invalid login attempt.');
        }

        $user = get_user_by('login', $storedUser);
        if (!$user) {
            wp_die('User not found.');
        }

        wp_set_current_user($user->ID);
        wp_set_auth_cookie($user->ID);
        do_action('wp_login', $user->user_login, $user);

        delete_option("sc_login_{$sessionCode}_token");
        delete_option("sc_login_{$sessionCode}_username");

        wp_redirect(admin_url());
        exit;
    }

    /**
     * Handle ping endpoint
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function handlePing(WP_REST_Request $request): WP_REST_Response
    {
        return new WP_REST_Response([
            'message' => 'Site is online',
            'site_id' => get_option('sc_site_id'),
        ], 200);
    }

    /**
     * Handle example data endpoint
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function handleExampleData(WP_REST_Request $request): WP_REST_Response
    {
        $parameters = $request->get_json_params();

        if (!isset($parameters['site_id'])) {
            // Additional validation could be added here
        }

        return new WP_REST_Response([
            'success' => true,
            'received' => $parameters,
        ]);
    }

    /**
     * Handle verify registration endpoint
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function handleVerifyRegistration(WP_REST_Request $request): WP_REST_Response
    {
        $parameters = $request->get_json_params();

        if (isset($parameters['registration_id'])) {
            $keyManager = new KeyManager();

            try {
                $decryptedRegId = $keyManager->decrypt($parameters['registration_id']);

                if ($decryptedRegId !== get_option('sc_registration_id')) {
                    return new WP_REST_Response([
                        'success' => false,
                        'message' => 'Unauthorized or invalid registration ID.',
                    ], 403);
                }
            } catch (\Exception $e) {
                return new WP_REST_Response([
                    'success' => false,
                    'message' => 'Invalid registration data.',
                ], 403);
            }
        }

        return new WP_REST_Response([
            'success' => true,
        ]);
    }

    /**
     * Handle execute command endpoint
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function handleExecuteCommand(WP_REST_Request $request): WP_REST_Response
    {
        $parameters = $request->get_json_params();

        if (!isset($parameters['body']) || !isset($parameters['body']['arguments'])) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Bad Request. Please ensure arguments are provided with the request.',
            ], 403);
        }

        $body = $parameters['body'];

        if (!isset($body['site_token']) || !isset($body['command'])) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Bad Request. Please ensure both site token and command are provided.',
            ], 403);
        }

        $siteToken = $body['site_token'];
        $command = $body['command'];

        $keyManager = new KeyManager();

        try {
            $decryptedSiteToken = $keyManager->decrypt($siteToken);
        } catch (\Exception $e) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Request authentication failed.',
            ], 401);
        }

        $siteTokenOption = get_option('sc_site_token');
        if ($decryptedSiteToken !== $siteTokenOption) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Request authentication failed.',
            ], 401);
        }

        $commandArguments = $body['arguments'] ?? [];

        try {
            $plugin = \_121Digital\Connect\Core\Plugin::getInstance();
            $commandDispatcher = $plugin->getComponent('command_dispatcher');
            $commandResponse = $commandDispatcher->dispatch($command, $commandArguments);

            return new WP_REST_Response([
                'success' => $commandResponse['success'],
                'message' => $commandResponse['message'],
                'data' => $commandResponse['data'],
            ], 200);
        } catch (\Exception $e) {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'An internal server error was raised during command execution: ' . $e->getMessage(),
            ], 500);
        }
    }
}
