<?php
/**
 * Standard Endpoints for Integrations
 *
 * @package FleekDash
 * @subpackage Integrations\Core
 */

namespace FleekDash\Integrations\Core;

defined('ABSPATH') || exit;

/**
 * Standard Endpoints class
 *
 * Provides a standardized way to register REST endpoints for integrations
 */
class StandardEndpoints
{
    /**
     * Base namespace for all FleekDash endpoints
     */
    const NAMESPACE = 'fleekdash/v1';

    /**
     * Standard permission callback for admin users
     *
     * @return bool
     */
    public static function admin_permission_check()
    {
        return current_user_can('manage_options');
    }

    /**
     * Standard permission callback for users who can edit posts
     *
     * @return bool
     */
    public static function editor_permission_check()
    {
        return current_user_can('edit_posts');
    }

    /**
     * Register a standard integration endpoint
     *
     * @param string $integration_id Integration ID
     * @param string $endpoint Endpoint path (without leading slash)
     * @param array $args Standard WP REST args
     * @return void
     */
    public static function register_integration_endpoint($integration_id, $endpoint, $args = [])
    {
        $defaults = [
            'permission_callback' => [self::class, 'admin_permission_check'],
        ];

        $args = array_merge($defaults, $args);
        $route = "/integrations/{$integration_id}/{$endpoint}";

        register_rest_route(self::NAMESPACE , $route, $args);

        error_log("StandardEndpoints: Registered {$route}");
    }

    /**
     * Register a chat endpoint for AI integrations
     *
     * @param string $integration_id Integration ID
     * @param callable $callback Callback function
     * @return void
     */
    public static function register_chat_endpoint($integration_id, $callback)
    {
        self::register_integration_endpoint($integration_id, 'chat', [
            'methods' => 'POST',
            'callback' => $callback,
            'permission_callback' => [self::class, 'editor_permission_check'],
            'args' => [
                'messages' => [
                    'required' => true,
                    'type' => 'array',
                    'description' => 'Array of chat messages',
                ],
                'stream' => [
                    'type' => 'boolean',
                    'default' => false,
                    'description' => 'Whether to stream the response',
                ],
                'context' => [
                    'type' => 'object',
                    'description' => 'Additional context for the chat',
                ],
            ],
        ]);
    }

    /**
     * Register a settings endpoint for integrations
     *
     * @param string $integration_id Integration ID
     * @param callable $get_callback GET callback
     * @param callable $update_callback POST callback
     * @return void
     */
    public static function register_settings_endpoint($integration_id, $get_callback, $update_callback)
    {
        // GET endpoint
        self::register_integration_endpoint($integration_id, 'settings', [
            'methods' => 'GET',
            'callback' => $get_callback,
        ]);

        // POST endpoint
        self::register_integration_endpoint($integration_id, 'settings', [
            'methods' => 'POST',
            'callback' => $update_callback,
            'args' => [
                'settings' => [
                    'required' => true,
                    'type' => 'object',
                    'description' => 'Settings object to update',
                ],
            ],
        ]);
    }

    /**
     * Register a webhook endpoint for integrations
     *
     * @param string $integration_id Integration ID
     * @param string $webhook_name Webhook name
     * @param callable $callback Callback function
     * @param string $permission Permission level ('public', 'editor', 'admin')
     * @return void
     */
    public static function register_webhook_endpoint($integration_id, $webhook_name, $callback, $permission = 'public')
    {
        $permission_callback = '__return_true'; // Default for public webhooks

        switch ($permission) {
            case 'editor':
                $permission_callback = [self::class, 'editor_permission_check'];
                break;
            case 'admin':
                $permission_callback = [self::class, 'admin_permission_check'];
                break;
        }

        self::register_integration_endpoint($integration_id, "webhook/{$webhook_name}", [
            'methods' => ['POST', 'GET'],
            'callback' => $callback,
            'permission_callback' => $permission_callback,
        ]);
    }

    /**
     * Register a data endpoint for integrations
     *
     * @param string $integration_id Integration ID
     * @param string $data_type Data type (e.g., 'posts', 'users', 'analytics')
     * @param callable $callback Callback function
     * @return void
     */
    public static function register_data_endpoint($integration_id, $data_type, $callback)
    {
        self::register_integration_endpoint($integration_id, "data/{$data_type}", [
            'methods' => 'GET',
            'callback' => $callback,
            'args' => [
                'limit' => [
                    'type' => 'integer',
                    'default' => 10,
                    'minimum' => 1,
                    'maximum' => 100,
                    'description' => 'Number of items to return',
                ],
                'offset' => [
                    'type' => 'integer',
                    'default' => 0,
                    'minimum' => 0,
                    'description' => 'Number of items to skip',
                ],
                'search' => [
                    'type' => 'string',
                    'description' => 'Search term',
                ],
            ],
        ]);
    }

    /**
     * Register a status endpoint for integrations
     *
     * @param string $integration_id Integration ID
     * @param callable $callback Callback function
     * @return void
     */
    public static function register_status_endpoint($integration_id, $callback)
    {
        self::register_integration_endpoint($integration_id, 'status', [
            'methods' => 'GET',
            'callback' => $callback,
            'permission_callback' => [self::class, 'editor_permission_check'],
        ]);
    }

    /**
     * Create a standardized success response
     *
     * @param mixed $data Response data
     * @param string $message Success message
     * @return \WP_REST_Response
     */
    public static function success_response($data = null, $message = 'Success')
    {
        $response = [
            'success' => true,
            'message' => $message,
        ];

        if ($data !== null) {
            $response['data'] = $data;
        }

        return rest_ensure_response($response);
    }

    /**
     * Create a standardized error response
     *
     * @param string $message Error message
     * @param int $status HTTP status code
     * @param string $code Error code
     * @return \WP_Error
     */
    public static function error_response($message, $status = 400, $code = 'error')
    {
        return new \WP_Error($code, $message, ['status' => $status]);
    }

    /**
     * Get all registered FleekDash endpoints
     *
     * @return array
     */
    public static function get_registered_endpoints()
    {
        $server = \rest_get_server();
        $routes = $server->get_routes();

        $fleekdash_routes = [];
        foreach ($routes as $route => $handlers) {
            if (strpos($route, '/' . self::NAMESPACE) === 0) {
                $fleekdash_routes[$route] = $handlers;
            }
        }

        return $fleekdash_routes;
    }

    /**
     * Validate request data against schema
     *
     * @param array $data Request data
     * @param array $schema Validation schema
     * @return bool|\WP_Error
     */
    public static function validate_request_data($data, $schema)
    {
        foreach ($schema as $field => $rules) {
            // Check required fields
            if (isset($rules['required']) && $rules['required'] && !isset($data[$field])) {
                return self::error_response("Field '{$field}' is required", 400, 'missing_field');
            }

            // Skip validation if field is not present and not required
            if (!isset($data[$field])) {
                continue;
            }

            // Type validation
            if (isset($rules['type'])) {
                $type = $rules['type'];
                $value = $data[$field];

                switch ($type) {
                    case 'string':
                        if (!is_string($value)) {
                            return self::error_response("Field '{$field}' must be a string", 400, 'invalid_type');
                        }
                        break;
                    case 'integer':
                        if (!is_int($value)) {
                            return self::error_response("Field '{$field}' must be an integer", 400, 'invalid_type');
                        }
                        break;
                    case 'boolean':
                        if (!is_bool($value)) {
                            return self::error_response("Field '{$field}' must be a boolean", 400, 'invalid_type');
                        }
                        break;
                    case 'array':
                        if (!is_array($value)) {
                            return self::error_response("Field '{$field}' must be an array", 400, 'invalid_type');
                        }
                        break;
                }
            }

            // Min/max validation for numbers
            if (isset($rules['minimum']) && is_numeric($data[$field]) && $data[$field] < $rules['minimum']) {
                return self::error_response("Field '{$field}' must be at least {$rules['minimum']}", 400, 'value_too_small');
            }

            if (isset($rules['maximum']) && is_numeric($data[$field]) && $data[$field] > $rules['maximum']) {
                return self::error_response("Field '{$field}' must be at most {$rules['maximum']}", 400, 'value_too_large');
            }
        }

        return true;
    }
}
