<?php

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

$block_dev = MAIL_BLOCK_DEV;

/**
 * Creates and configures a PHPMailer instance.
 *
 * @return PHPMailer A configured PHPMailer instance
 */
function createMailer(): PHPMailer
{
    $mail = new PHPMailer();
    $mail->isSMTP();
    $mail->CharSet = 'UTF-8';
    $mail->Host = MAIL_HOST;
    $mail->SMTPOptions = [
        'ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true,
        ],
    ];
    $mail->SMTPDebug = MAIL_DEBUG;
    $mail->SMTPAuth = MAIL_AUTH;
    $mail->SMTPSecure = MAIL_ENCRYPTION;
    $mail->Port = MAIL_PORT;
    $mail->Username = MAIL_USERNAME;
    $mail->Password = MAIL_PASSWORD;
    $mail->From = MAIL_FROM;
    $mail->FromName = MAIL_FROM_NAME;

    return $mail;
}

/**
 * Adds addresses to PHPMailer by type.
 *
 * @param PHPMailer $mail The PHPMailer instance
 * @param array $addresses List of email addresses
 * @param string $type Address type: 'to', 'cc', or 'bcc'
 * @return void
 * @throws Exception
 */
function addAddressesByType(PHPMailer $mail, array $addresses, string $type): void
{
    foreach ($addresses as $address) {
        switch ($type) {
            case 'to':
                $mail->addAddress($address);
                break;
            case 'cc':
                $mail->addCC($address);
                break;
            case 'bcc':
                $mail->addBCC($address);
                break;
        }
    }
}

/**
 * Prepares email addresses for sending.
 *
 * @param PHPMailer $mail PHPMailer instance
 * @param array $addresses Array of addresses (to, cc, bcc)
 * @return void
 * @throws Exception
 */
function prepareAddresses(PHPMailer $mail, array $addresses): void
{
    $mail->clearAllRecipients();

    if (isset($addresses['to']) && is_array($addresses['to'])) {
        addAddressesByType($mail, $addresses['to'], 'to');
    }

    if (isset($addresses['cc']) && is_array($addresses['cc'])) {
        addAddressesByType($mail, $addresses['cc'], 'cc');
    }

    if (isset($addresses['bcc']) && is_array($addresses['bcc'])) {
        addAddressesByType($mail, $addresses['bcc'], 'bcc');
    }
}

/**
 * Replaces application placeholders in the email body.
 *
 * @param PHPMailer $mail PHPMailer instance
 * @return void
 */
function applyAppPlaceholders(PHPMailer $mail): void
{
    $body = $mail->Body;
    $body = str_replace('%APP_NAME%', APP_NAME, $body);
    $body = str_replace('%APP_URL%', rtrim(APP_URL, '/'), $body);
    $body = str_replace('%LOGO_URL%', LOGO_URL, $body);
    $mail->Body = $body;
}

/**
 * Prepares an HTML email using a template.
 *
 * @param PHPMailer $mail PHPMailer instance
 * @param string $include Template file name
 * @param bool $dev Development mode flag
 * @param array $data Additional data for the template
 * @return void
 */
function prepareHtmlEmail(PHPMailer $mail, string $include, bool $dev = false, array $data = []): void
{
    $htmlBody = '';
    include "email_files/$include.slm";

    $mail->isHTML(true);
    $mail->Body = $htmlBody;

    applyAppPlaceholders($mail);
}

/**
 * Sends an email with a security token.
 *
 * @param string $email Recipient email address
 * @param array $data Token data (token, fecha_creacion, fecha_expiracion)
 * @param bool $debug Debug mode flag
 * @return bool True if email was sent successfully
 */
function sendToken(string $email, array $data, bool $debug = false): bool
{
    $response = _response(true, 'Email not sent.', ['email' => $email]);

    $send = false;

    $log_type = 'error';
    $log_data = [];
    try {
        $mail = createMailer();

        $addresses = [
            'to' => [$email],
        ];

        prepareAddresses($mail, $addresses);

        $mail->Subject = sprintf('[%s] Security Verification [%s]', APP_NAME, getTimestamp());
        $log_data['subject'] = $mail->Subject;

        prepareHtmlEmail($mail, 'sendToken');

        $mail->Body = str_replace('%TOKEN_ACCESO%', $data['token'], $mail->Body);
        $mail->Body = str_replace('%FECHA_CREACION%', $data['fecha_creacion'], $mail->Body);
        $mail->Body = str_replace('%FECHA_EXPIRACION%', $data['fecha_expiracion'], $mail->Body);

        if ($mail->send()) {
            $send = true;

            $response['error'] = false;
            $response['message'] = 'Email sent.';

            $log_type = 'success';
        }
    } catch (Exception $e) {
        $response['message'] = $e->getMessage();
    } finally {
        $log_data['return'] = $response;
        addToLog($log_type, 'system', __FUNCTION__, $log_data);
    }

    return $send;
}
