<?php
declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
  header('Access-Control-Allow-Methods: POST, OPTIONS');
  header('Access-Control-Allow-Headers: Content-Type');
  http_response_code(204);
  exit;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  http_response_code(405);
  echo json_encode(['ok' => false, 'error' => 'Method not allowed']);
  exit;
}

$configPath = __DIR__ . '/config.php';
if (!is_file($configPath)) {
  http_response_code(500);
  echo json_encode([
    'ok' => false,
    'error' => 'Server misconfigured: missing api/config.php (copy from config.example.php)',
  ]);
  exit;
}

/** @var array{smtp_host:string,smtp_port:int,smtp_user:string,smtp_pass:string,booking_to:string,from_name:string} $config */
$config = require $configPath;

$raw = file_get_contents('php://input');
$data = json_decode($raw ?: '{}', true);
if (!is_array($data)) {
  http_response_code(400);
  echo json_encode(['ok' => false, 'error' => 'Invalid JSON body']);
  exit;
}

function field(array $data, string $key): string
{
  $value = $data[$key] ?? '';
  return is_string($value) ? trim($value) : '';
}

$firstName = field($data, 'firstName');
$lastName = field($data, 'lastName');
$email = field($data, 'email');
$designBrief = field($data, 'designBrief');
$phone = field($data, 'phone');
$pronouns = field($data, 'pronouns');
$workedTogether = field($data, 'workedTogether');
$city = field($data, 'city');
$placementSize = field($data, 'placementSize');
$existingTattoos = field($data, 'existingTattoos');
$colorOrBlackGray = field($data, 'colorOrBlackGray');

if ($firstName === '' || $lastName === '' || $email === '' || $designBrief === '') {
  http_response_code(400);
  echo json_encode([
    'ok' => false,
    'error' => 'Missing required fields: firstName, lastName, email, and designBrief',
  ]);
  exit;
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
  http_response_code(400);
  echo json_encode(['ok' => false, 'error' => 'Invalid email address']);
  exit;
}

$orDash = static function (string $value): string {
  return $value !== '' ? $value : '—';
};

$rows = [
  ['Name', trim($firstName . ' ' . $lastName)],
  ['Email', $email],
  ['Phone', $orDash($phone)],
  ['Pronouns', $orDash($pronouns)],
  ['Worked together before?', $orDash($workedTogether)],
  ['City', $orDash($city)],
  ['Design brief', $designBrief],
  ['Placement / size', $orDash($placementSize)],
  ['Existing tattoos nearby?', $orDash($existingTattoos)],
  ['Color or Black & Gray', $orDash($colorOrBlackGray)],
];

$textLines = ["New booking inquiry", ''];
$htmlRows = '';
foreach ($rows as [$label, $value]) {
  $textLines[] = $label . ': ' . $value;
  $htmlRows .= '<tr><td style="padding:8px 12px;border-bottom:1px solid #e5e5e5;font-weight:600;vertical-align:top;white-space:nowrap;">'
    . htmlspecialchars($label, ENT_QUOTES, 'UTF-8')
    . '</td><td style="padding:8px 12px;border-bottom:1px solid #e5e5e5;vertical-align:top;">'
    . nl2br(htmlspecialchars($value, ENT_QUOTES, 'UTF-8'))
    . '</td></tr>';
}

$subject = 'Booking inquiry — ' . $firstName . ' ' . $lastName . ($city !== '' ? ' (' . $city . ')' : '');
$html = '<div style="font-family:Georgia,serif;line-height:1.5;color:#111;">'
  . '<h1 style="font-size:20px;margin:0 0 16px;">New booking inquiry</h1>'
  . '<p style="margin:0 0 20px;">Submitted via meirayaelart.com booking form.</p>'
  . '<table style="border-collapse:collapse;width:100%;max-width:640px;font-size:14px;">'
  . $htmlRows
  . '</table></div>';
$text = implode("\n", $textLines);

try {
  smtp_send($config, $config['booking_to'], $subject, $text, $html, $email);
  echo json_encode(['ok' => true]);
} catch (Throwable $e) {
  http_response_code(502);
  echo json_encode(['ok' => false, 'error' => $e->getMessage() ?: 'Failed to send email via SMTP']);
}

/**
 * @param array{smtp_host:string,smtp_port:int,smtp_user:string,smtp_pass:string,from_name:string} $config
 */
function smtp_send(
  array $config,
  string $to,
  string $subject,
  string $text,
  string $html,
  string $replyTo
): void {
  $host = $config['smtp_host'];
  $port = (int) $config['smtp_port'];
  $user = $config['smtp_user'];
  $pass = $config['smtp_pass'];
  $fromName = $config['from_name'];

  $errno = 0;
  $errstr = '';
  $socket = @stream_socket_client(
    'ssl://' . $host . ':' . $port,
    $errno,
    $errstr,
    30,
    STREAM_CLIENT_CONNECT,
    stream_context_create(['ssl' => ['verify_peer' => true, 'verify_peer_name' => true]])
  );

  if (!$socket) {
    throw new RuntimeException('SMTP connection failed: ' . $errstr);
  }

  stream_set_timeout($socket, 30);

  $expect = static function ($socket, array $codes) use (&$read): void {
    $read = '';
    while (($line = fgets($socket, 515)) !== false) {
      $read .= $line;
      if (isset($line[3]) && $line[3] === ' ') {
        break;
      }
    }
    $code = (int) substr($read, 0, 3);
    if (!in_array($code, $codes, true)) {
      throw new RuntimeException('SMTP error (' . $code . '): ' . trim($read));
    }
  };

  $write = static function ($socket, string $command) use ($expect): void {
    fwrite($socket, $command . "\r\n");
  };

  $expect($socket, [220]);
  $write($socket, 'EHLO meirayaelart.com');
  $expect($socket, [250]);
  $write($socket, 'AUTH LOGIN');
  $expect($socket, [334]);
  $write($socket, base64_encode($user));
  $expect($socket, [334]);
  $write($socket, base64_encode($pass));
  $expect($socket, [235]);
  $write($socket, 'MAIL FROM:<' . $user . '>');
  $expect($socket, [250]);
  $write($socket, 'RCPT TO:<' . $to . '>');
  $expect($socket, [250, 251]);
  $write($socket, 'DATA');
  $expect($socket, [354]);

  $boundary = 'b_' . bin2hex(random_bytes(12));
  $encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
  $encodedFromName = '=?UTF-8?B?' . base64_encode($fromName) . '?=';

  $headers = [
    'Date: ' . date('r'),
    'From: ' . $encodedFromName . ' <' . $user . '>',
    'To: <' . $to . '>',
    'Reply-To: <' . $replyTo . '>',
    'Subject: ' . $encodedSubject,
    'MIME-Version: 1.0',
    'Content-Type: multipart/alternative; boundary="' . $boundary . '"',
  ];

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

  $message = implode("\r\n", $headers) . "\r\n\r\n" . $body;
  // Dot-stuffing
  $message = preg_replace('/^\./m', '..', $message) ?? $message;

  fwrite($socket, $message . "\r\n.\r\n");
  $expect($socket, [250]);
  $write($socket, 'QUIT');
  fclose($socket);
}
