<?php

declare(strict_types=1);

namespace MailerPress\Api;

\defined('ABSPATH') || exit;

use DI\DependencyException;
use DI\NotFoundException;
use MailerPress\Core\Attributes\Endpoint;
use MailerPress\Core\EmailManager\EmailServiceManager;
use MailerPress\Core\Kernel;
use WP_Error;

enum CONNEXION_RESULT: string
{
    case NOTOK = 'KO';
    case OK = 'OK';
}

class Options
{
    #[Endpoint(
        'get-active-provider',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit'],
    )]
    public function activeProvider(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        return new \WP_REST_Response(
            get_option('mailerpress_email_services', [
                'default_service' => 'php',
                'activated' => ['php'],
                'services' => [
                    'php' => [
                        'conf' => [
                            'default_email' => '',
                            'default_name' => '',
                        ],
                    ],
                ],
            ])
        );
    }


    #[Endpoint(
        'connect-provider',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit'],
    )]
    public function post(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $key = $request->get_param('key');
        $activated = $request->get_param('activated');
        $config = $request->get_param('config');

        Kernel::getContainer()->get(EmailServiceManager::class)->saveServiceConfiguration($key, $config, $activated);

        return rest_ensure_response(
            get_option('mailerpress_email_services')
        );
    }

    #[Endpoint(
        'connect-provider',
        methods: 'DELETE',
        permissionCallback: [Permissions::class, 'canEdit'],
    )]
    public function remove(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $key = $request->get_param('key');

        Kernel::getContainer()->get(EmailServiceManager::class)->removeService($key);

        return rest_ensure_response(
            get_option('mailerpress_email_services')
        );
    }

    #[Endpoint(
        'set-primary-email-service',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit'],
    )]
    public function setPrimaryEmailService(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $key = $request->get_param('key');

        Kernel::getContainer()->get(EmailServiceManager::class)->setActiveService($key);

        return rest_ensure_response(
            get_option('mailerpress_email_services')
        );
    }

    /**
     * @throws DependencyException
     * @throws NotFoundException
     */
    #[Endpoint(
        'send-email',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit']
    )]
    public function sendEmail(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $to = $request->get_param('to');
        $html = $request->get_param('html');
        $key = $request->get_param('key');
        $mailer = Kernel::getContainer()->get(EmailServiceManager::class)->getActiveServiceByKey($key);
        $config = $mailer->getConfig();


        if (
            empty($config['conf']['default_email'])
            || empty($config['conf']['default_name'])
        ) {
            $globalSender = get_option('mailerpress_global_email_senders');
            if (is_string($globalSender)) {
                $globalSender = json_decode($globalSender, true);
            }
            $config['conf']['default_email'] = $globalSender['fromAddress'];
            $config['conf']['default_name'] = $globalSender['fromName'];
        }

        $result = $mailer->sendEmail([
            'to' => $to,
            'html' => $html,
            'body' => __('Yup, it works! You can start blasting emails to the moon.', 'mailerpress'),
            'subject' => __('This is a Sending Method Test', 'mailerpress'),
            'sender_name' => $config['conf']['default_name'],
            'sender_to' => $config['conf']['default_email'],
            'apiKey' => $config['conf']['api_key'] ?? '',
            'isTest' => true,
        ]);

        // Si c'est un WP_Error, retourner une réponse d'erreur avec le message détaillé
        if (is_wp_error($result)) {
            return new \WP_Error(
                $result->get_error_code(),
                $result->get_error_message(),
                ['status' => 400]
            );
        }

        // Si c'est false, retourner une erreur générique
        if ($result === false) {
            return new \WP_Error(
                'send_email_failed',
                __('An error occurred while sending the test email. Please check your configuration and try again.', 'mailerpress'),
                ['status' => 400]
            );
        }

        return rest_ensure_response(['success' => true]);
    }

    #[Endpoint(
        'disconnect-provider',
        methods: 'GET',
        permissionCallback: [Permissions::class, 'canEdit']
    )]
    public function disconnectProvider(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        delete_option('mailerpress_esp_config');
        delete_option('mailerpress_senders');
        delete_transient('mailerpress_list');

        return rest_ensure_response('done');
    }

    #[Endpoint(
        'save-theme',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit']
    )]
    public function saveTheme(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $theme = $request->get_param('name');
        if (empty($theme)) {
            return new \WP_Error('invalid_theme', 'Theme name is required.', ['status' => 400]);
        }
        update_option('mailerpress_theme', sanitize_text_field($theme), 'Core');
        return rest_ensure_response([]);
    }

    #[Endpoint(
        'create-option',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit']
    )]
    public function createOrUpdateOption(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $optionName = $request->get_param('name');
        $optionValue = $request->get_param('value');
        if (empty($optionName)) {
            return new \WP_Error('invalid_option', 'Option name is required.', ['status' => 400]);
        }
        $optionName = sanitize_key($optionName);

        // Si c'est une chaîne simple, ne pas l'encoder en JSON (évite le double encodage)
        // Si c'est un objet ou un tableau, l'encoder en JSON
        if (is_string($optionValue)) {
            // Vérifier si c'est déjà une chaîne JSON encodée (commence par " ou { ou [)
            $trimmed = trim($optionValue);
            if (
                (substr($trimmed, 0, 1) === '"' && substr($trimmed, -1) === '"') ||
                (substr($trimmed, 0, 1) === '{' && substr($trimmed, -1) === '}') ||
                (substr($trimmed, 0, 1) === '[' && substr($trimmed, -1) === ']')
            ) {
                // C'est déjà du JSON, décoder puis réencoder proprement
                $decoded = json_decode($optionValue, true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    // C'était du JSON, réencoder
                    $optionValue = wp_json_encode($decoded);
                } else {
                    // Ce n'était pas du JSON valide, garder tel quel mais sanitizer
                    $optionValue = sanitize_text_field($optionValue);
                }
            } else {
                // Chaîne simple, ne pas encoder en JSON
                $optionValue = sanitize_text_field($optionValue);
            }
        } else {
            // Objet ou tableau, encoder en JSON
            $optionValue = wp_json_encode($optionValue);
        }

        return rest_ensure_response(
            update_option($optionName, $optionValue)
        );
    }


    #[Endpoint(
        'option/(?P<name>[a-zA-Z0-9-_]+)',
        methods: 'GET',
        permissionCallback: [Permissions::class, 'canView']
    )]
    public function getOption(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $option_name = $request->get_param('name');
        $option_value = get_option($option_name);

        if (is_null($option_value)) {
            return new WP_Error('no_option', 'Option not found', ['status' => 404]);
        }

        return rest_ensure_response([
            'option_name' => $option_name,
            'option_value' => $option_value,
        ]);
    }

    #[Endpoint(
        'delete-option',
        methods: 'DELETE',
        permissionCallback: [Permissions::class, 'canEdit']
    )]
    public function deleteOption(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $optionName = $request->get_param('name');
        if (empty($optionName)) {
            return new \WP_Error('invalid_option', 'Option name is required.', ['status' => 400]);
        }

        $optionName = sanitize_key($optionName);

        // Optionally, whitelist allowed option names here

        $deleted = delete_option($optionName);

        return rest_ensure_response($deleted);
    }


    #[Endpoint(
        'user/setup-completed',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit']  // You already have this in your code
    )]
    public function markSetupCompleted(\WP_REST_Request $request): \WP_Error|\WP_HTTP_Response|\WP_REST_Response
    {
        $userId = get_current_user_id();

        if (!$userId) {
            return new \WP_Error('no_user', 'User not authenticated.', ['status' => 401]);
        }

        $completed = $request->get_param('completed');

        if (!in_array($completed, ['yes', 'no'], true)) {
            return new \WP_Error('invalid_param', 'The completed value must be "yes" or "no".', ['status' => 400]);
        }

        update_user_meta($userId, 'mailerpress_setup_completed', $completed);

        return rest_ensure_response([
            'success' => true,
            'completed' => $completed,
        ]);
    }

    #[Endpoint(
        'test-bounce-connection',
        methods: 'POST',
        permissionCallback: [Permissions::class, 'canEdit']
    )]
    public function testBounceConnection(\WP_REST_Request $request): \WP_REST_Response|\WP_Error
    {
        $host = $request->get_param('host');
        $port = $request->get_param('port') ?? 993;
        $username = $request->get_param('username');
        $password = $request->get_param('password');
        $validateCert = $request->get_param('validateCert') ?? true;

        if (empty($host) || empty($username) || empty($password)) {
            return new \WP_Error('invalid_params', __('Missing IMAP credentials.', 'mailerpress'), ['status' => 400]);
        }

        $flags = "/imap/ssl" . (!$validateCert ? "/novalidate-cert" : '');
        $mailbox = sprintf("{%s:%d%s}INBOX", $host, $port, $flags);

        imap_timeout(IMAP_OPENTIMEOUT, 5);

        $imap = @imap_open($mailbox, $username, $password, 0, 1);
        if (!$imap) {
            return new \WP_Error(
                'imap_connection_failed',
                imap_last_error() ?: __('Unable to connect to IMAP server.', 'mailerpress'),
                ['status' => 400]
            );
        }

        imap_close($imap);
        return rest_ensure_response(['success' => true]);
    }
}
