<?php
// ═══════════════════════════════════════════════════════════
//  FICTION IGNITION — api/contact/index.php
//  POST /api/contact/
//
//  Security layers (defense in depth):
//   1. Rate limiting  — max 3 submissions per IP per hour
//   2. Input length   — hard limits on all fields
//   3. Sanitization   — strips HTML, scripts, injection patterns
//   4. Email validation — filter_var + domain check
//   5. Honeypot check — bot trap field
//   6. Content check  — blocks known spam signatures
// ═══════════════════════════════════════════════════════════

declare(strict_types=1);

require_once __DIR__ . '/../lib/config.php';
require_once __DIR__ . '/../lib/mailer.php';

fi_json_headers();

if ($_SERVER['REQUEST_METHOD'] !== 'POST') fi_error('Method not allowed.', 405);

$input = json_decode(file_get_contents('php://input'), true) ?? [];

// ── Rate limiting (DB-backed, per IP) ─────────────────────
// Requires a rate_limit table — create with:
// CREATE TABLE IF NOT EXISTS rate_limits (
//   id          BIGINT AUTO_INCREMENT PRIMARY KEY,
//   ip_hash     CHAR(64) NOT NULL,
//   action      VARCHAR(32) NOT NULL,
//   created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
//   INDEX idx_ip_action_time (ip_hash, action, created_at)
// ) ENGINE=InnoDB;

function check_rate_limit(string $action, int $maxHits, int $windowSeconds): void {
    try {
        $db     = fi_db();
        $ipHash = hash('sha256', $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'); // Never store raw IPs

        // Count recent submissions
        $stmt = $db->prepare('
            SELECT COUNT(*) FROM rate_limits
            WHERE ip_hash = ? AND action = ? AND created_at > DATE_SUB(NOW(), INTERVAL ? SECOND)
        ');
        $stmt->execute([$ipHash, $action, $windowSeconds]);
        $count = (int) $stmt->fetchColumn();

        if ($count >= $maxHits) {
            fi_error('Too many submissions. Please wait a while before trying again.', 429);
        }

        // Log this submission
        $db->prepare('INSERT INTO rate_limits (ip_hash, action) VALUES (?,?)')->execute([$ipHash, $action]);

        // Clean up old entries (housekeeping, 1% of requests)
        if (random_int(1, 100) === 1) {
            $db->prepare('DELETE FROM rate_limits WHERE created_at < DATE_SUB(NOW(), INTERVAL 2 HOUR)')->execute();
        }
    } catch (PDOException) {
        // If rate_limit table doesn't exist yet, skip silently
        // (Create the table via schema or just add it manually)
    }
}

// ── Sanitization ──────────────────────────────────────────
function sanitize_contact_input(string $value, int $maxLen): string {
    // Truncate to max length first
    $value = mb_substr($value, 0, $maxLen);

    // Strip all HTML/XML tags
    $value = strip_tags($value);

    // Strip PHP tags (belt and suspenders after strip_tags)
    $value = preg_replace('/<\?[\s\S]*?\?>/i', '', $value);

    // Strip script injection patterns
    $value = preg_replace('/javascript\s*:/i', '', $value);
    $value = preg_replace('/vbscript\s*:/i', '', $value);
    $value = preg_replace('/on\w+\s*=/i', '', $value);   // onclick=, onerror=, etc.

    // Strip template injection markers
    $value = preg_replace('/\{\{[\s\S]*?\}\}/', '', $value);  // {{ }}
    $value = preg_replace('/\{%[\s\S]*?%\}/', '', $value);    // {% %}
    $value = preg_replace('/<%[\s\S]*?%>/', '', $value);      // <% %>

    // Strip null bytes
    $value = str_replace("\0", '', $value);

    // Normalize line endings
    $value = preg_replace('/\r\n|\r/', "\n", $value);

    // Collapse excessive whitespace (preserve single newlines)
    $value = preg_replace('/[^\S\n]{2,}/', ' ', $value);

    return trim($value);
}

// ── Spam keyword check ────────────────────────────────────
function has_spam_content(string $text): bool {
    $spamPatterns = [
        '/\bviagra\b/i', '/\bcasino\b/i', '/\bcrypto\b/i',
        '/\bclick here\b/i', '/\bfree money\b/i',
        '/https?:\/\/[^\s]{50,}/i',   // Very long URLs
        '/(.)\1{8,}/',                  // Repeated characters
    ];
    foreach ($spamPatterns as $pattern) {
        if (preg_match($pattern, $text)) return true;
    }
    return false;
}

// ── Honeypot check ────────────────────────────────────────
// If the hidden 'website' field has any value, it's a bot
if (!empty($input['website'])) {
    // Return success to fool the bot but don't send the email
    fi_ok(['message' => 'Message sent successfully.']);
}

// ── Rate limit: 3 contact submissions per IP per hour ─────
check_rate_limit('contact', 3, 3600);

// ── Validate & sanitize ───────────────────────────────────
$name    = sanitize_contact_input($input['name']    ?? '', 100);
$email   = sanitize_contact_input($input['email']   ?? '', 254);
$subject = sanitize_contact_input($input['subject'] ?? '', 80);
$message = sanitize_contact_input($input['message'] ?? '', 2000);

// Name
if (mb_strlen($name) < 2)   fi_error('Name must be at least 2 characters.');
if (mb_strlen($name) > 100) fi_error('Name is too long.');

// Email
$email = strtolower(trim($email));
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) fi_error('Please enter a valid email address.');
// Check the domain has at least one dot (extra sanity check)
$domain = substr($email, strpos($email, '@') + 1);
if (substr_count($domain, '.') < 1) fi_error('Please enter a valid email address.');

// Subject — must match an allowed value
$allowedSubjects = ['General Question', 'Billing & Subscription', 'Technical Issue', 'Feature Request', 'Account Help', 'Other'];
if (!in_array($subject, $allowedSubjects, true)) fi_error('Please select a valid subject.');

// Message
if (mb_strlen(trim($message)) < 10)   fi_error('Message must be at least 10 characters.');
if (mb_strlen($message) > 2000)       fi_error('Message is too long.');

// Spam check
if (has_spam_content($name . ' ' . $message)) {
    fi_error('Your message was flagged as potential spam. Please contact us directly at support@fiction-ignition.com');
}

// ── Build and send support email ──────────────────────────
$supportEmail = 'support@fiction-ignition.com';
$appUrl       = rtrim(env('APP_URL'), '/');
$submittedAt  = date('F j, Y \a\t g:i a T');
$ipHash       = hash('sha256', $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0');

// Format message for email (preserve line breaks)
$messageHtml = nl2br(htmlspecialchars($message, ENT_QUOTES, 'UTF-8'));
$messagePlain = $message;

$html = <<<HTML
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8">
<style>
  body { font-family:'Segoe UI',Arial,sans-serif; background:#f2ebe0; margin:0; padding:0; }
  .wrap { max-width:620px; margin:32px auto; background:#fff; border-radius:12px; overflow:hidden; box-shadow:0 4px 24px rgba(0,0,0,.1); }
  .header { background:#1b2e5e; padding:24px 32px; }
  .header h1 { color:#fff; font-size:1.2rem; margin:0; font-family:Georgia,serif; }
  .header p { color:rgba(255,255,255,.6); font-size:.8rem; margin:4px 0 0; }
  .body { padding:28px 32px; }
  .field-row { margin-bottom:16px; padding-bottom:16px; border-bottom:1px solid #eee; }
  .field-row:last-child { border-bottom:none; margin-bottom:0; }
  .label { font-size:.7rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:#8a9ab0; margin-bottom:4px; }
  .value { font-size:.95rem; color:#1a2440; line-height:1.6; }
  .subject-badge { display:inline-block; background:#e8f0fe; color:#1b2e5e; padding:3px 10px; border-radius:20px; font-size:.8rem; font-weight:600; }
  .message-box { background:#faf6f0; border:1px solid rgba(27,46,94,.12); border-radius:8px; padding:16px; font-size:.93rem; color:#2a3a5a; line-height:1.75; }
  .footer { background:#f5f7fc; padding:16px 32px; border-top:1px solid #eee; }
  .footer p { font-size:.75rem; color:#8a9ab0; margin:0; }
  .reply-btn { display:inline-block; background:#e8610a; color:#fff !important; text-decoration:none; padding:10px 22px; border-radius:6px; font-weight:600; font-size:.88rem; margin-top:16px; }
</style>
</head>
<body>
<div class="wrap">
  <div class="header">
    <h1>🔥 New Contact Form Submission</h1>
    <p>Fiction Ignition · {$submittedAt}</p>
  </div>
  <div class="body">
    <div class="field-row">
      <div class="label">From</div>
      <div class="value"><strong>{$name}</strong></div>
    </div>
    <div class="field-row">
      <div class="label">Email</div>
      <div class="value"><a href="mailto:{$email}" style="color:#e8610a">{$email}</a></div>
    </div>
    <div class="field-row">
      <div class="label">Subject</div>
      <div class="value"><span class="subject-badge">{$subject}</span></div>
    </div>
    <div class="field-row">
      <div class="label">Message</div>
      <div class="message-box">{$messageHtml}</div>
    </div>
    <a href="mailto:{$email}?subject=Re: {$subject} — Fiction Ignition" class="reply-btn">Reply to {$name} →</a>
  </div>
  <div class="footer">
    <p>Submitted via fictionignition.com/contact · IP Hash: {$ipHash}</p>
  </div>
</div>
</body>
</html>
HTML;

$plainText = <<<TEXT
New Contact Form Submission — Fiction Ignition
Submitted: {$submittedAt}

From:    {$name}
Email:   {$email}
Subject: {$subject}

Message:
{$messagePlain}

---
IP Hash: {$ipHash}
TEXT;

$sent = fi_send_email(
    $supportEmail,
    'Fiction Ignition Support',
    "[Contact Form] {$subject} — from {$name}",
    $html,
    $plainText
);

if (!$sent) {
    // Log failure but don't expose to user — avoid info leakage
    error_log("Contact form email failed. From: {$email}, Subject: {$subject}");
    fi_error('We could not deliver your message right now. Please email us directly at support@fiction-ignition.com', 503);
}

// ── Auto-reply to sender ──────────────────────────────────
$autoReplyHtml = <<<HTML
<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<style>
  body { font-family:'Segoe UI',Arial,sans-serif; background:#f2ebe0; margin:0; }
  .wrap { max-width:580px; margin:32px auto; background:#fff; border-radius:12px; overflow:hidden; box-shadow:0 4px 24px rgba(0,0,0,.1); }
  .header { background:#1b2e5e; padding:28px 32px; text-align:center; }
  .header h1 { color:#fff; font-size:1.3rem; margin:0; font-family:Georgia,serif; }
  .body { padding:32px; }
  .body h2 { color:#1b2e5e; font-family:Georgia,serif; margin-top:0; }
  .body p { color:#4a5a7a; line-height:1.75; font-size:.95rem; }
  .quote-box { background:#faf6f0; border-left:3px solid #e8610a; padding:12px 16px; border-radius:0 8px 8px 0; margin:16px 0; font-size:.88rem; color:#5a6a8a; line-height:1.65; }
  .footer { background:#0e1726; padding:18px 32px; text-align:center; }
  .footer p { color:rgba(255,255,255,.35); font-size:.75rem; margin:0; }
</style>
</head>
<body>
<div class="wrap">
  <div class="header"><h1>🔥 Fiction Ignition</h1></div>
  <div class="body">
    <h2>We got your message, {$name}!</h2>
    <p>Thank you for reaching out. We've received your message and will respond within <strong>one business day</strong>.</p>
    <p>Here's what you sent us:</p>
    <div class="quote-box">
      <strong>{$subject}</strong><br><br>
      {$messageHtml}
    </div>
    <p style="font-size:.85rem;color:#8a9ab0">If your question is urgent, you can also reach us directly at
    <a href="mailto:support@fiction-ignition.com" style="color:#e8610a">support@fiction-ignition.com</a>.</p>
  </div>
  <div class="footer">
    <p>© 2025 Fiction Ignition · By Mark Bogner · <a href="{$appUrl}/privacy.html" style="color:rgba(255,255,255,.4)">Privacy Policy</a></p>
  </div>
</div>
</body>
</html>
HTML;

// Send auto-reply (non-fatal if it fails)
fi_send_email($email, $name, 'We received your message — Fiction Ignition', $autoReplyHtml);

fi_ok(['message' => 'Message sent successfully.']);
