<?php
declare(strict_types=1);

/**
 * Minimal SMTP helper driven by the SMTP_* env vars in .env.example.
 */

function mail_env_value(string $key): string {
  $value = $_ENV[$key] ?? getenv($key) ?? '';
  return trim((string)$value);
}

function mail_is_configured(): bool {
  $required = ['SMTP_HOST', 'SMTP_PORT', 'SMTP_USER', 'SMTP_PASS', 'MAIL_FROM'];
  foreach ($required as $k) {
    if (mail_env_value($k) === '') return false;
  }
  return true;
}

function mail_smtp_timeout(): int {
  $val = mail_env_value('SMTP_TIMEOUT');
  return $val === '' ? 30 : max(5, (int)$val);
}

function mail_use_starttls(): bool {
  $raw = strtolower(mail_env_value('SMTP_STARTTLS') ?: 'true');
  return $raw !== 'false' && $raw !== '0' && $raw !== 'no';
}

function mail_subject_header(string $subject): string {
  if (function_exists('mb_encode_mimeheader')) {
    return mb_encode_mimeheader($subject, 'UTF-8');
  }
  return preg_replace('/[\r\n]+/', ' ', $subject);
}

function mail_dot_stuff(string $body): string {
  if ($body === '') return '';
  $body = preg_replace('/(\r?\n)\./', "$1..", $body);
  if (str_starts_with($body, '.')) {
    $body = '.' . $body;
  }
  return $body;
}

function mail_send_message(string $to, string $subject, string $body): array {
  if (!mail_is_configured()) {
    return ['sent' => false, 'error' => 'SMTP configuration incomplete'];
  }

  $host = mail_env_value('SMTP_HOST');
  $port = (int)mail_env_value('SMTP_PORT');
  $user = mail_env_value('SMTP_USER');
  $pass = mail_env_value('SMTP_PASS');
  $from = mail_env_value('MAIL_FROM');
  $fromName = mail_env_value('MAIL_FROM_NAME') ?: 'MY.TOWN Blogger';

  if ($port <= 0) $port = 587;
  $secure = $port === 465;
  $remote = ($secure ? 'ssl://' : 'tcp://') . $host . ':' . $port;
  $timeout = mail_smtp_timeout();

  $context = stream_context_create([
    'ssl' => [
      'verify_peer' => false,
      'verify_peer_name' => false,
    ],
  ]);

  $fp = @stream_socket_client($remote, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context);
  if (!$fp) {
    return ['sent' => false, 'error' => "SMTP connection failed: $errstr ($errno)"];
  }
  stream_set_timeout($fp, $timeout);

  $response = mail_read_response($fp);
  if ($response['code'] !== 220) {
    fclose($fp);
    return ['sent' => false, 'error' => "SMTP rejected connection: {$response['line']}"];
  }

  $hostname = $_SERVER['SERVER_NAME'] ?? 'localhost';
  if (!mail_smtp_cmd($fp, "EHLO $hostname", [250], $response)) {
    fclose($fp);
    return ['sent' => false, 'error' => 'SMTP EHLO failed'];
  }

  if (!$secure && mail_use_starttls()) {
    if (!mail_smtp_cmd($fp, 'STARTTLS', [220], $response)) {
      fclose($fp);
      return ['sent' => false, 'error' => 'SMTP STARTTLS failed'];
    }
    if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
      fclose($fp);
      return ['sent' => false, 'error' => 'Failed to enable TLS'];
    }
    if (!mail_smtp_cmd($fp, "EHLO $hostname", [250], $response)) {
      fclose($fp);
      return ['sent' => false, 'error' => 'SMTP EHLO after STARTTLS failed'];
    }
  }

  if (!mail_smtp_cmd($fp, 'AUTH LOGIN', [334], $response)) {
    fclose($fp);
    return ['sent' => false, 'error' => 'SMTP AUTH login not accepted'];
  }
  if (!mail_smtp_cmd($fp, base64_encode($user), [334], $response)) {
    fclose($fp);
    return ['sent' => false, 'error' => 'SMTP AUTH username rejected'];
  }
  if (!mail_smtp_cmd($fp, base64_encode($pass), [235], $response)) {
    fclose($fp);
    return ['sent' => false, 'error' => 'SMTP AUTH password rejected'];
  }

  if (!mail_smtp_cmd($fp, "MAIL FROM:<$from>", [250], $response)) {
    fclose($fp);
    return ['sent' => false, 'error' => 'MAIL FROM rejected'];
  }
  if (!mail_smtp_cmd($fp, "RCPT TO:<$to>", [250, 251], $response)) {
    fclose($fp);
    return ['sent' => false, 'error' => 'RCPT TO rejected'];
  }

  if (!mail_smtp_cmd($fp, 'DATA', [354], $response)) {
    fclose($fp);
    return ['sent' => false, 'error' => 'SMTP DATA rejected'];
  }

  $headers = [
    'Date: ' . date(DATE_RFC2822),
    'From: ' . mail_header_from($fromName, $from),
    'To: ' . $to,
    'Subject: ' . mail_subject_header($subject),
    'MIME-Version: 1.0',
    'Content-Type: text/plain; charset=utf-8',
    'Content-Transfer-Encoding: 8bit',
  ];
  $message = implode("\r\n", $headers) . "\r\n\r\n" . mail_dot_stuff($body) . "\r\n.\r\n";
  fwrite($fp, $message);

  $response = mail_read_response($fp);
  if ($response['code'] !== 250) {
    fclose($fp);
    return ['sent' => false, 'error' => "SMTP DATA finalize failed: {$response['line']}"];
  }

  mail_smtp_cmd($fp, 'QUIT', [221], $response);
  fclose($fp);
  return ['sent' => true, 'error' => ''];
}

function mail_header_from(string $name, string $email): string {
  $nameClean = preg_replace('/[\\r\\n"]+/', '', $name);
  if ($nameClean === '') return $email;
  return '"' . $nameClean . '" <' . $email . '>';
}

function mail_read_response($fp): array {
  $line = '';
  $code = 0;
  while (($row = fgets($fp)) !== false) {
    $line = rtrim($row, "\r\n");
    if (preg_match('/^(\d{3})[ -]/', $row, $m)) {
      $code = (int)$m[1];
      if (isset($row[3]) && $row[3] === ' ') break;
    }
  }
  return ['code' => $code, 'line' => $line];
}

function mail_smtp_cmd($fp, string $cmd, array $accepted, array &$response): bool {
  fwrite($fp, $cmd . "\r\n");
  $response = mail_read_response($fp);
  return in_array($response['code'], $accepted, true);
}
