<?php

declare(strict_types=1);

namespace CloudXM\SDK\Support\Traits;

use CloudXM\SDK\Support\HasLogger;

trait RespondsToAjax
{
    use HasLogger;

    /** Text domain for translations */
    protected string $textDomain = 'cloudxm-sdk';

    /**
     * Set the text domain for translations
     *
     * @param string $textDomain
     * @return void
     */
    protected function setTextDomain(string $textDomain): void
    {
        $this->textDomain = $textDomain;
    }

    /** Verify nonce and capability. */
    protected function guardAjax(string $nonceAction, string $capability = 'manage_options'): void
    {
        $nonce = $_POST['nonce'] ?? '';
        if (!wp_verify_nonce($nonce, $nonceAction)) {
            $this->logError('AJAX security check failed: invalid nonce', [
                'nonce_action' => $nonceAction,
                'user_id' => get_current_user_id(),
                'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
            ]);
            wp_send_json_error(['message' => __('Invalid security token', $this->textDomain)], 403);
        }
        if (!current_user_can($capability)) {
            $this->logWarning('AJAX access denied: insufficient permissions', [
                'capability' => $capability,
                'user_id' => get_current_user_id(),
                'user_capabilities' => wp_get_current_user()->allcaps ?? []
            ]);
            wp_send_json_error(['message' => __('Insufficient permissions', $this->textDomain)], 403);
        }
    }

    /** Send success response. */
    protected function sendSuccess(mixed $data = [], string $message = ''): void
    {
        if ($message) {
            $data['message'] = $message;
        }
        wp_send_json_success($data);
    }

    /**
     * Handle an exception in AJAX handler with proper security and logging
     *
     * @param \Throwable $e The exception that occurred
     * @param string|null $context Additional context for logging
     */
    protected function handleAjaxError(\Throwable $e, ?string $context = null): void
    {
        // Always log the error details for debugging
        $this->logError('AJAX error occurred', [
            'exception_class' => get_class($e),
            'exception_message' => $e->getMessage(),
            'exception_file' => $e->getFile(),
            'exception_line' => $e->getLine(),
            'exception_trace' => $e->getTraceAsString(),
            'context' => $context,
            'user_id' => get_current_user_id(),
            'user_roles' => wp_get_current_user()->roles ?? [],
            'request_data' => $this->sanitizeRequestData($_POST),
            'server_data' => $this->sanitizeServerData($_SERVER)
        ]);

        // Check if user has admin privileges to see debug info
        $isAdmin = current_user_can('manage_options');
        $showDebugInfo = $isAdmin && defined('WP_DEBUG') && WP_DEBUG;

        $response = [
            'message' => __('An error occurred. Please try again or contact support if the problem persists.', $this->textDomain)
        ];

        // Include debug information only for admins in debug mode
        if ($showDebugInfo) {
            $response['debug'] = [
                'error_type' => get_class($e),
                'error_message' => $e->getMessage(),
                'error_file' => $e->getFile() . ':' . $e->getLine(),
                'context' => $context
            ];
        }

        wp_send_json_error($response, 500);
    }

    /**
     * Sanitize request data for logging (remove sensitive information)
     *
     * @param array $data
     * @return array
     */
    private function sanitizeRequestData(array $data): array
    {
        $sanitized = $data;

        // Remove or mask sensitive fields
        $sensitiveFields = ['password', 'pwd', 'pass', 'key', 'secret', 'token', 'nonce'];

        foreach ($sensitiveFields as $field) {
            if (isset($sanitized[$field])) {
                $sanitized[$field] = '[REDACTED]';
            }
        }

        return $sanitized;
    }

    /**
     * Sanitize server data for logging (remove sensitive information)
     *
     * @param array $server
     * @return array
     */
    private function sanitizeServerData(array $server): array
    {
        $sanitized = [];

        // Only include non-sensitive server information
        $allowedKeys = ['REQUEST_METHOD', 'REQUEST_URI', 'HTTP_USER_AGENT', 'REMOTE_ADDR', 'HTTP_HOST'];

        foreach ($allowedKeys as $key) {
            if (isset($server[$key])) {
                $sanitized[$key] = $server[$key];
            }
        }

        return $sanitized;
    }
}
