<?php

namespace RtmMail\Actions\Handlers;

use Exception;
use RtmMail\Cryptor;
use RtmMail\Logger;
use RtmMailVendor\Dependencies\PHPMailer\PHPMailer\PHPMailer;
use function get_user_by;

/**
 * Handles the action of testing SMTP settings by attempting to connect to an SMTP server using PHPMailer.
 */
class TestSmtpSettingsAction extends AbstractActionHandler
{
    /**
     * Constructor sets up the action identifier.
     */
    public function __construct()
    {
        parent::__construct('test_smtp_settings', 'rtm_mail_test_smtp');
    }

    /**
     * Executes the action to test SMTP settings.
     *
     * @return array The result of the operation with success status and message.
     */
    public function handleAction(): array
    {
        $user_data = get_user_by('id', get_current_user_id());
        $user_info = $user_data ? $user_data->ID . ' (' . $user_data->display_name . ')' : 'Unknown User';

        // Verify nonce for security
        if (!$this->verifyNonce()) {
            return [
                'success' => false,
                'message' => __('Invalid nonce!', 'rtm-mail'),
            ];
        }

        // Attempt to setup and verify SMTP connection
        try {
            $phpMailer = new PHPMailer(true);
            $this->logAttempt($user_info); // Log the connection attempt
            $this->initSmtp($phpMailer); // Initialize and test SMTP settings
            Logger::info(
                "SMTP Connection Successful",
                "SMTP test connection was successful",
                'default',
                'Log',
                ['user' => $user_info]
            );
            return [
                'success' => true,
                'message' => 'SMTP connection successful.'
            ];
        } catch (Exception $e) {
            Logger::error(
                "SMTP Test Failure",
                $e->getMessage(),
                'default',
                'Log',
                ['user' => $user_info]
            );
            return [
                'success' => false,
                'message' => 'SMTP error: ' . $e->getMessage()
            ];
        }
    }

    /**
     * Initializes PHPMailer with SMTP settings and attempts a connection.
     *
     * @param PHPMailer $phpMailer PHPMailer instance for testing the SMTP connection.
     * @throws Exception If SMTP settings are incomplete or connection fails.
     */
    private function initSmtp($phpMailer): void
    {
        $settings = get_option('rtm_mail_smtp_settings');
        if (empty($settings) || !isset($settings['smtp_settings']['other'])) {
            throw new Exception('SMTP settings are incomplete.');
        }

        $smtp = $settings['smtp_settings']['other'];
        $phpMailer->isSMTP();
        $phpMailer->Host = $smtp['other_smtp_host'];
        $phpMailer->Port = $smtp['other_smtp_port'];
        $phpMailer->SMTPSecure = $smtp['other_smtp_encryption'] === 'ssl' ? PHPMailer::ENCRYPTION_SMTPS :
            ($smtp['other_smtp_encryption'] === 'tls' ? PHPMailer::ENCRYPTION_STARTTLS : '');
        $phpMailer->SMTPAuth = !empty($smtp['other_smtp_username']) && !empty($smtp['other_smtp_password']);

        if ($phpMailer->SMTPAuth) {
            $encryption_key = get_option('rtm_mail_smtp_key', false);
            $phpMailer->Username = $smtp['other_smtp_username'];
            $phpMailer->Password = Cryptor::decrypt($smtp['other_smtp_password'], $encryption_key);
        }

        if (!$phpMailer->smtpConnect()) {
            throw new Exception('Failed to connect to SMTP server.');
        }
        $phpMailer->smtpClose();
    }

    /**
     * Logs the attempt to connect to the SMTP server.
     *
     * @param string $user_info Information about the user making the attempt.
     */
    private function logAttempt(string $user_info): void
    {
        Logger::info(
            "SMTP Connection Attempt",
            "Attempting SMTP connection",
            'default',
            'Log',
            ['user' => $user_info]
        );
    }
}
