<?php
function gp_setting(PDO $pdo, string $key, string $default = ''): string
{
    $stmt = $pdo->prepare("SELECT setting_value FROM settings WHERE setting_key = :k LIMIT 1");
    $stmt->execute([':k' => $key]);
    $v = $stmt->fetchColumn();
    return $v !== false ? (string)$v : $default;
}

function gp_mailer_settings(PDO $pdo): array
{
    return [
        'enabled'    => gp_setting($pdo, 'smtp_enabled', '0') === '1',
        'host'       => gp_setting($pdo, 'smtp_host', ''),
        'port'       => (int)gp_setting($pdo, 'smtp_port', '587'),
        'secure'     => gp_setting($pdo, 'smtp_secure', 'tls'),
        'username'   => gp_setting($pdo, 'smtp_username', ''),
        'password'   => gp_setting($pdo, 'smtp_password', ''),
        'from_email' => gp_setting($pdo, 'smtp_from_email', 'projects@gopools.gr'),
        'from_name'  => gp_setting($pdo, 'smtp_from_name', 'GoPools CRM'),
        'reply_to'   => gp_setting($pdo, 'smtp_reply_to', ''),
    ];
}

function gp_mime_header(string $text): string
{
    return '=?UTF-8?B?' . base64_encode($text) . '?=';
}

function gp_mail_is_html(string $body): bool
{
    return $body !== strip_tags($body);
}

function gp_mail_html_to_text(string $html): string
{
    $text = preg_replace('/<\s*br\s*\/?>/i', "\n", $html);
    $text = preg_replace('/<\/p>/i', "\n\n", (string)$text);
    $text = preg_replace('/<\/div>/i', "\n", (string)$text);
    $text = preg_replace('/<\/li>/i', "\n", (string)$text);
    $text = preg_replace('/<li[^>]*>/i', '- ', (string)$text);
    $text = strip_tags((string)$text);
    $text = html_entity_decode((string)$text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    $text = preg_replace("/\n{3,}/", "\n\n", (string)$text);
    return trim((string)$text);
}

function gp_smtp_send(PDO $pdo, string $to, string $subject, string $body, array $attachments = [], string &$error = ''): bool
{
    $cfg = gp_mailer_settings($pdo);
    if (!$cfg['enabled']) {
        $error = 'SMTP is disabled.';
        return false;
    }
    if ($cfg['host'] === '' || $cfg['username'] === '' || $cfg['password'] === '' || $cfg['from_email'] === '') {
        $error = 'SMTP settings are incomplete.';
        return false;
    }

    $host = $cfg['host'];
    $port = (int)$cfg['port'];
    $secure = strtolower(trim($cfg['secure']));
    $transport = ($secure === 'ssl') ? 'ssl://' . $host : $host;

    $socket = @stream_socket_client($transport . ':' . $port, $errno, $errstr, 20, STREAM_CLIENT_CONNECT);
    if (!$socket) {
        $error = 'SMTP connect failed: ' . $errstr . ' (' . $errno . ')';
        return false;
    }
    stream_set_timeout($socket, 20);

    $read = function() use ($socket): string {
        $data = '';
        while (($line = fgets($socket, 515)) !== false) {
            $data .= $line;
            if (preg_match('/^\d{3}\s/', $line)) break;
        }
        return $data;
    };
    $write = function(string $cmd) use ($socket): void {
        fwrite($socket, $cmd . "\r\n");
    };
    $expect = function(string $response, array $codes) use (&$error): bool {
        $code = (int)substr(trim($response), 0, 3);
        if (!in_array($code, $codes, true)) {
            $error = 'SMTP unexpected response: ' . trim($response);
            return false;
        }
        return true;
    };

    if (!$expect($read(), [220])) { fclose($socket); return false; }
    $write('EHLO gopools.local');
    if (!$expect($read(), [250])) { fclose($socket); return false; }

    if ($secure === 'tls') {
        $write('STARTTLS');
        if (!$expect($read(), [220])) { fclose($socket); return false; }
        if (!@stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
            $error = 'SMTP TLS negotiation failed.';
            fclose($socket);
            return false;
        }
        $write('EHLO gopools.local');
        if (!$expect($read(), [250])) { fclose($socket); return false; }
    }

    $write('AUTH LOGIN');
    if (!$expect($read(), [334])) { fclose($socket); return false; }
    $write(base64_encode($cfg['username']));
    if (!$expect($read(), [334])) { fclose($socket); return false; }
    $write(base64_encode($cfg['password']));
    if (!$expect($read(), [235])) { fclose($socket); return false; }

    $write('MAIL FROM:<' . $cfg['from_email'] . '>');
    if (!$expect($read(), [250])) { fclose($socket); return false; }
    $write('RCPT TO:<' . $to . '>');
    if (!$expect($read(), [250, 251])) { fclose($socket); return false; }
    $write('DATA');
    if (!$expect($read(), [354])) { fclose($socket); return false; }

    $isHtml = gp_mail_is_html($body);
    $plainTextBody = $isHtml ? gp_mail_html_to_text($body) : $body;
    $plainTextBody = str_replace(["\r\n", "\r"], "\n", (string)$plainTextBody);
    $plainTextBody = preg_replace("/\n{3,}/", "\n\n", (string)$plainTextBody);
    $plainTextBody = trim((string)$plainTextBody) . "\n";

    $mixedBoundary = 'gopools_mixed_' . md5((string)microtime(true));
    $altBoundary = 'gopools_alt_' . md5((string)(microtime(true) . '_alt'));

    $headers = [];
    $headers[] = 'From: ' . gp_mime_header($cfg['from_name']) . ' <' . $cfg['from_email'] . '>';
    if ($cfg['reply_to'] !== '') $headers[] = 'Reply-To: ' . $cfg['reply_to'];
    $headers[] = 'To: <' . $to . '>';
    $headers[] = 'Subject: ' . gp_mime_header($subject);
    $headers[] = 'MIME-Version: 1.0';
    $headers[] = 'Content-Type: multipart/mixed; boundary="' . $mixedBoundary . '"';

    $message = implode("\r\n", $headers) . "\r\n\r\n";
    $message .= '--' . $mixedBoundary . "\r\n";
    $message .= 'Content-Type: multipart/alternative; boundary="' . $altBoundary . '"' . "\r\n\r\n";

    $message .= '--' . $altBoundary . "\r\n";
    $message .= "Content-Type: text/plain; charset=UTF-8\r\n";
    $message .= "Content-Transfer-Encoding: base64\r\n\r\n";
    $message .= chunk_split(base64_encode($plainTextBody)) . "\r\n";

    if ($isHtml) {
        $message .= '--' . $altBoundary . "\r\n";
        $message .= "Content-Type: text/html; charset=UTF-8\r\n";
        $message .= "Content-Transfer-Encoding: base64\r\n\r\n";
        $message .= chunk_split(base64_encode($body)) . "\r\n";
    }

    $message .= '--' . $altBoundary . "--\r\n";

    foreach ($attachments as $att) {
        $path = (string)($att['path'] ?? '');
        $name = (string)($att['name'] ?? basename($path));
        if ($path === '' || !is_file($path)) continue;
        $data = file_get_contents($path);
        if ($data === false) continue;
        $message .= '--' . $mixedBoundary . "\r\n";
        $message .= 'Content-Type: application/octet-stream; name="' . addslashes($name) . '"' . "\r\n";
        $message .= "Content-Transfer-Encoding: base64\r\n";
        $message .= 'Content-Disposition: attachment; filename="' . addslashes($name) . '"' . "\r\n\r\n";
        $message .= chunk_split(base64_encode($data)) . "\r\n";
    }

    $message .= '--' . $mixedBoundary . "--\r\n.\r\n";
    fwrite($socket, $message);

    if (!$expect($read(), [250])) { fclose($socket); return false; }
    $write('QUIT');
    fclose($socket);
    return true;
}
