<?php
// ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);
require_once __DIR__ . '/security.php';
require_once __DIR__ . '/logging.php';

$tenant = enrep_tenant_segment($_REQUEST['tenant'] ?? (defined('TENANT_URL') ? TENANT_URL : ''));
if (!defined('CONFIG_LOADED') && $tenant !== '' && file_exists('../../' . $tenant . '/config.php')) {
    require_once('../../' . $tenant . '/config.php');
}
if (!defined('CONFIG_LOADED') && file_exists('/config.php')) {
    require_once('/config.php');
}

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

$mailExt = $mailExt ?? '';
$attach = '';
$fstring = '';
$logAttachments = [];

if ($mailExt != "auto") {
    require '../packages/mailer/Exception.php';
    require '../packages/mailer/PHPMailer.php';
    require '../packages/mailer/SMTP.php';
} else {
    require '../../packages/mailer/Exception.php';
    require '../../packages/mailer/PHPMailer.php';
    require '../../packages/mailer/SMTP.php';
}

function sendmail_tenant_path(string $tenant, string ...$parts): string
{
    if ($tenant === '') {
        enrep_fail(400, 'Missing tenant');
    }

    return enrep_tenant_path($tenant, ...$parts);
}

function storeImage($n)
{
    global $tenant;

    $f = $_FILES[$n];
    $filename = enrep_safe_filename((string)$f["name"]);
    move_uploaded_file($_FILES[$n]["tmp_name"], sendmail_tenant_path($tenant, 'storage', $filename));

    return $filename;
}

function sendmail_add_attachment(PHPMailer $mail, string $tenant, string $source, string $file): void
{
    if ($file === '') {
        return;
    }

    $mail->addAttachment(sendmail_tenant_path($tenant, $source, $file));
}

function sendmail_log_attachment(string $source, string $file, string $type = ''): array
{
    return [
        'file' => $file,
        'source' => trim($source, '/'),
        'path' => trim(trim($source, '/') . '/' . $file, '/'),
        'type' => $type !== '' ? $type : pathinfo($file, PATHINFO_EXTENSION),
    ];
}

function sendmail_graph_post(string $url, array $headers, $body): array
{
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_TIMEOUT => 60,
        ]);

        $response = curl_exec($ch);
        $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($response === false) {
            throw new \RuntimeException('Microsoft Graph request failed: ' . $error);
        }

        return ['status' => $status, 'body' => (string)$response];
    }

    $headerText = implode("\r\n", $headers);
    $context = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => $headerText,
            'content' => $body,
            'timeout' => 60,
            'ignore_errors' => true,
        ],
    ]);

    $response = file_get_contents($url, false, $context);
    $status = 0;
    if (!empty($http_response_header[0]) && preg_match('/\s(\d{3})\s/', $http_response_header[0], $matches)) {
        $status = (int)$matches[1];
    }

    if ($response === false) {
        throw new \RuntimeException('Microsoft Graph request failed');
    }

    return ['status' => $status, 'body' => (string)$response];
}

function sendmail_graph_access_token(string $tenantId, string $clientId, string $clientSecret): string
{
    $tokenUrl = 'https://login.microsoftonline.com/' . rawurlencode($tenantId) . '/oauth2/v2.0/token';
    $body = http_build_query([
        'client_id' => $clientId,
        'scope' => 'https://graph.microsoft.com/.default',
        'client_secret' => $clientSecret,
        'grant_type' => 'client_credentials',
    ]);

    $result = sendmail_graph_post($tokenUrl, ['Content-Type: application/x-www-form-urlencoded'], $body);
    $data = json_decode($result['body'], true);

    if ($result['status'] < 200 || $result['status'] >= 300 || empty($data['access_token'])) {
        $message = is_array($data) && !empty($data['error_description'])
            ? $data['error_description']
            : $result['body'];
        throw new \RuntimeException('Microsoft 365 token request failed: ' . $message);
    }

    return (string)$data['access_token'];
}

function sendmail_graph_send(PHPMailer $mail): void
{
    $tenantId = trim((string)getEmailSystemSettings('host'));
    $clientId = trim((string)getEmailSystemSettings('username'));
    $clientSecret = (string)getEmailSystemSettings('password');
    $from = trim((string)getEmailSystemSettings('from'));

    if ($tenantId === '' || $clientId === '' || $clientSecret === '' || $from === '') {
        throw new \RuntimeException('Microsoft 365 mail settings are incomplete');
    }

    if (!$mail->preSend()) {
        throw new \RuntimeException($mail->ErrorInfo ?: 'Unable to prepare email for Microsoft 365');
    }

    $token = sendmail_graph_access_token($tenantId, $clientId, $clientSecret);
    $sendUrl = 'https://graph.microsoft.com/v1.0/users/' . rawurlencode($from) . '/sendMail';
    $result = sendmail_graph_post($sendUrl, [
        'Authorization: Bearer ' . $token,
        'Content-Type: text/plain',
    ], base64_encode($mail->getSentMIMEMessage()));

    if ($result['status'] < 200 || $result['status'] >= 300) {
        $data = json_decode($result['body'], true);
        $message = is_array($data) && !empty($data['error']['message'])
            ? $data['error']['message']
            : $result['body'];
        throw new \RuntimeException('Microsoft 365 send failed: ' . $message);
    }
}

if ($mailExt != "auto") {
    $header = file_get_contents('../includes/email/email_template.php');
} else {
    $header = file_get_contents('../../includes/email/email_template.php');
}

$message = enrep_request_string('message', '', 200000);
$subject = enrep_request_string('subject', '', 500);
$reference = enrep_request_string('reference', '', 255);

$header = str_replace('[SITE]', getCompanyDetails('web'), $header);
$header = str_replace('[MESSAGE]', nl2br($message), $header);
$header = str_replace('[LOGO]', getCompanyDetails('web') . '/images/company/logo_thumb.jpg?' . rand(), $header);
$header = str_replace('[ENREP]', getCompanyDetails('web') . '/images/logo_border.png?' . rand(), $header);
$header = str_replace('[ADDRESS]', getCompanyDetails('addressLong'), $header);
$header = str_replace('[CONTACT]', getCompanyDetails('contact'), $header);
$header = str_replace('[SUBJECT]', $subject, $header);

$mail = new PHPMailer(true);

try {
    $mailType = (int)getEmailSystemSettings('type');
    $mail->SMTPDebug = 0;
    $mail->CharSet = 'UTF-8';
    $mail->Encoding = '8bit';
    if ($mailType === 1) {
        $mail->isSMTP();
    } elseif ($mailType === 0) {
        $mail->isSendmail();
    }
    if ($mailType === 1) {
        $mail->Host = getEmailSystemSettings('host');
        $mail->SMTPAuth = true;
        $mail->Username = getEmailSystemSettings('username');
        $mail->Password = getEmailSystemSettings('password');
        $mail->SMTPSecure = 'tls';
        $mail->Port = 587;
    }
    $mail->setFrom(getEmailSystemSettings('from'), getEmailSystemSettings('from_name'));

    if (!empty($_REQUEST['report_1'])) {
        $file = enrep_request_string('report_1', '', 255);
        $source = enrep_request_string('source_1', '', 255);
        sendmail_add_attachment($mail, $tenant, $source, $file);
        $attach = "|attached 1";
        $fstring = "with the file(s) " . $file;
        $logAttachments[] = sendmail_log_attachment($source, $file, 'report');
    }
    if (!empty($_REQUEST['file_1'])) {
        $file = enrep_request_string('file_1', '', 255);
        $source = enrep_request_string('source_1', '', 255);
        sendmail_add_attachment($mail, $tenant, $source, $file);
        $attach = "|attached 1";
        $fstring = "with the file(s) " . $file;
        $logAttachments[] = sendmail_log_attachment($source, $file, 'file');
    }
    if (!empty($_REQUEST['file_2'])) {
        $file = enrep_request_string('file_2', '', 255);
        $source = enrep_request_string('source_2', '', 255);
        sendmail_add_attachment($mail, $tenant, $source, $file);
        $attach = "|attached 1";
        $fstring = "with the file(s) " . $file;
        $logAttachments[] = sendmail_log_attachment($source, $file, 'file');
    }
    if (!empty($_FILES['attachment_1']['name'])) {
        $file1 = storeImage('attachment_1');
        $mail->addAttachment(sendmail_tenant_path($tenant, 'storage', $file1));
        $attach .= "|attached 1";
        $fstring = "with the file(s) " . $file1;
        $logAttachments[] = sendmail_log_attachment('storage', $file1, 'uploaded');
    }
    if (!empty($_FILES['attachment_2']['name'])) {
        $file2 = storeImage('attachment_2');
        $mail->addAttachment(sendmail_tenant_path($tenant, 'storage', $file2));
        $attach .= "|attached 2";
        $fstring .= "," . $file2;
        $logAttachments[] = sendmail_log_attachment('storage', $file2, 'uploaded');
    }
    if (!empty($_FILES['attachment_3']['name'])) {
        $file3 = storeImage('attachment_3');
        $mail->addAttachment(sendmail_tenant_path($tenant, 'storage', $file3));
        $attach .= "|attached 3";
        $fstring .= "," . $file3;
        $logAttachments[] = sendmail_log_attachment('storage', $file3, 'uploaded');
    }
    if (!empty($_FILES['attachment_4']['name'])) {
        $file4 = storeImage('attachment_4');
        $mail->addAttachment(sendmail_tenant_path($tenant, 'storage', $file4));
        $attach .= "|attached 4";
        $fstring .= "," . $file4;
        $logAttachments[] = sendmail_log_attachment('storage', $file4, 'uploaded');
    }

    $rstring = "Sent Email to ";
    $mail->clearAddresses();
    $uniqueEmails = [];
    $tracking_id = uniqid('em_', true);

    foreach ($_REQUEST as $key => $value) {
        if (preg_match('/^recipient_\d+$/', (string)$key) && !empty($value) && !is_array($value)) {
            $email = trim(strtolower((string)$value));
            if (filter_var($email, FILTER_VALIDATE_EMAIL) && !in_array($email, $uniqueEmails, true)) {
                $mail->addAddress($email);
                $rstring .= "," . $email;
                $uniqueEmails[] = $email;
            }
        }
    }

    $email_type = enrep_request_string('source_1', '', 255);
    $sent_at = date('Y-m-d H:i:s');
    $header .= '<img src="' . getCompanyDetails('web') . '/track_open.php?id=' . $tracking_id . '" width="1" height="1" style="display:none;" alt="" />';

    $mail->addReplyTo(getEmailSystemSettings('from'), getEmailSystemSettings('from_name'));
    $mail->isHTML(true);
    $mail->Subject = $subject;
    $mail->Body = $header;
    $mail->AltBody = $message;

    if ($mailType === 2) {
        sendmail_graph_send($mail);
    } else {
        $mail->send();
    }
    enrep_log_email('sent', $subject, $uniqueEmails, $logAttachments, 'Sent email', [
        'reference' => $reference,
        'tracking_id' => $tracking_id,
    ]);
    echo json_encode(['status' => 'success', 'message' => 'Email sent successfully.']);

    foreach ($uniqueEmails as $email) {
        $stmt = $GLOBALS['con']->prepare("INSERT INTO email_tracking (tracking_id, recipient, email_type, subject, reference, sent_at) VALUES (?, ?, ?, ?, ?, ?)");
        $stmt->bind_param('ssssss', $tracking_id, $email, $email_type, $subject, $reference, $sent_at);
        $stmt->execute();
        $stmt->close();
    }
} catch (\Throwable $e) {
    $errorInfo = $mail->ErrorInfo ?: $e->getMessage();
    enrep_log_email('send_failed', $subject, $uniqueEmails ?? [], $logAttachments, 'Email failed: ' . $errorInfo, [
        'reference' => $reference,
    ]);
    echo json_encode(['status' => 'error', 'message' => 'Message could not be sent. Mailer Error: ' . $errorInfo]);
}
?>
