// src/pages/api/send-message.js
export const prerender = false;

// Simple in-memory rate limiting (for single server)
const rateLimitMap = new Map();
const RATE_LIMIT_DETECTION_WINDOW = 15 * 60 * 1000; // 15 minutes - window to detect abuse
const RATE_LIMIT_BLOCK_DURATION = 60 * 60 * 1000; // 1 hour - how long to block after abuse detected
const MAX_REQUESTS = 3; // Max 3 submissions per 15 minutes per IP

// Attack monitoring
const attackLog = [];
const MAX_ATTACK_LOG_SIZE = 1000;

function logSuspiciousActivity(ip, reason, data = {}) {
  const logEntry = {
    timestamp: new Date().toISOString(),
    ip,
    reason,
    userAgent: data.userAgent || 'unknown',
    data: data.formData || {}
  };
  
  attackLog.push(logEntry);
  
  // Keep log size manageable
  if (attackLog.length > MAX_ATTACK_LOG_SIZE) {
    attackLog.shift();
  }
  
  // Log to console for real-time monitoring
  console.log(`🚨 SUSPICIOUS ACTIVITY: ${reason} from ${ip}`, logEntry);
  
  // Log to file for persistence
  try {
    const fs = require('fs');
    const path = require('path');
    
    const logDir = path.resolve(process.cwd(), 'logs');
    const attackLogFile = path.join(logDir, 'security-attacks.log');
    
    if (!fs.existsSync(logDir)) {
      fs.mkdirSync(logDir, { recursive: true });
    }
    
    const logMessage = `${logEntry.timestamp} - ${reason} from ${ip} - UA: ${logEntry.userAgent}\n`;
    fs.appendFileSync(attackLogFile, logMessage);
  } catch (error) {
    console.error('Failed to log attack:', error);
  }
}

function getRealIP(request) {
  const forwarded = request.headers.get('x-forwarded-for');
  const realIP = request.headers.get('x-real-ip');
  const cfIP = request.headers.get('cf-connecting-ip');
  
  if (forwarded) {
    return forwarded.split(',')[0].trim();
  }
  if (realIP) {
    return realIP;
  }
  if (cfIP) {
    return cfIP;
  }
  
  return 'unknown';
}

function isRateLimited(ip) {
  const now = Date.now();
  const userData = rateLimitMap.get(ip) || { requests: [], blockedUntil: null };
  
  // Check if IP is currently blocked
  if (userData.blockedUntil && now < userData.blockedUntil) {
    const remainingTime = Math.ceil((userData.blockedUntil - now) / 1000 / 60); // minutes
    logSuspiciousActivity(ip, 'BLOCKED_IP_ATTEMPT', {
      remainingBlockTime: remainingTime + ' minutes',
      blockedUntil: new Date(userData.blockedUntil).toISOString()
    });
    return true;
  }
  
  // Clean old requests (only keep requests from the detection window)
  const recentRequests = userData.requests.filter(time => now - time < RATE_LIMIT_DETECTION_WINDOW);
  
  // Check if this request would exceed the limit
  if (recentRequests.length >= MAX_REQUESTS) {
    // Block the IP for 1 hour
    const blockUntil = now + RATE_LIMIT_BLOCK_DURATION;
    userData.blockedUntil = blockUntil;
    userData.requests = recentRequests; // Keep the requests that triggered the block
    rateLimitMap.set(ip, userData);
    
    logSuspiciousActivity(ip, 'RATE_LIMIT_EXCEEDED_BLOCKED', {
      requestCount: recentRequests.length,
      detectionWindow: RATE_LIMIT_DETECTION_WINDOW / 1000 / 60 + ' minutes',
      blockDuration: RATE_LIMIT_BLOCK_DURATION / 1000 / 60 + ' minutes',
      blockedUntil: new Date(blockUntil).toISOString()
    });
    return true;
  }
  
  // Add current request and update the map
  recentRequests.push(now);
  userData.requests = recentRequests;
  userData.blockedUntil = null; // Clear any previous block
  rateLimitMap.set(ip, userData);
  
  return false;
}

function validateMessage(data, ip, userAgent) {
  const { name, email, subject, message } = data;
  
  // Check message length first (legitimate validation errors)
  if (message.length < 10) {
    logSuspiciousActivity(ip, 'MESSAGE_TOO_SHORT', {
      userAgent,
      messageLength: message.length,
      formData: { name, email, subject }
    });
    return {
      type: 'validation_error',
      message: 'Your message is too short. Please provide at least 10 characters.',
      logReason: 'MESSAGE_TOO_SHORT'
    };
  }
  
  if (message.length > 5000) {
    logSuspiciousActivity(ip, 'MESSAGE_TOO_LONG', {
      userAgent,
      messageLength: message.length,
      formData: { name, email, subject }
    });
    return {
      type: 'validation_error', 
      message: 'Your message is too long. Please keep it under 5000 characters.',
      logReason: 'MESSAGE_TOO_LONG'
    };
  }
  
  // Check for excessive links (could be legitimate user error)
  const linkCount = (message.match(/http[s]?:\/\//g) || []).length;
  if (linkCount > 2) {
    logSuspiciousActivity(ip, 'EXCESSIVE_LINKS', {
      userAgent,
      linkCount,
      formData: { name, email, subject }
    });
    return {
      type: 'validation_error',
      message: 'Please limit your message to maximum 2 links.',
      logReason: 'EXCESSIVE_LINKS'
    };
  }
  
  return null; // No validation errors
}

function detectSpam(data, ip, userAgent) {
  const { name, email, subject, message, website } = data;
  
  // Check for honeypot field (definitely spam - hide detection)
  if (website && website.trim() !== '') {
    logSuspiciousActivity(ip, 'HONEYPOT_TRIGGERED', {
      userAgent,
      formData: { name, email, subject, honeypotValue: website }
    });
    return {
      type: 'spam_hidden',
      message: 'Thank you for your message! We\'ll get back to you soon.',
      logReason: 'HONEYPOT_TRIGGERED'
    };
  }
  
  // Check for suspicious patterns (spam - hide detection)
  const suspiciousPatterns = [
    { pattern: /viagra|cialis|casino|poker|loan|mortgage|bitcoin|crypto/i, name: 'SPAM_KEYWORDS' },
    { pattern: /\b(click here|buy now|limited time|act now)\b/i, name: 'MARKETING_SPAM' },
    { pattern: /http[s]?:\/\/.*\.(tk|ml|ga|cf|bit\.ly)/i, name: 'SUSPICIOUS_DOMAINS' },
    { pattern: /\b(seo|backlink|link building|rank higher)\b/i, name: 'SEO_SPAM' },
  ];
  
  const fullText = `${name} ${email} ${subject} ${message}`.toLowerCase();
  
  for (const { pattern, name: patternName } of suspiciousPatterns) {
    if (pattern.test(fullText)) {
      logSuspiciousActivity(ip, patternName, {
        userAgent,
        formData: { name, email, subject, messageLength: message.length }
      });
      return {
        type: 'spam_hidden',
        message: 'Thank you for your message! We\'ll get back to you soon.',
        logReason: patternName
      };
    }
  }
  
  // Check for repeated characters (likely spam - hide detection)
  if (/(.)\1{10,}/.test(message)) {
    logSuspiciousActivity(ip, 'SUSPICIOUS_REPETITION', {
      userAgent,
      formData: { name, email, subject }
    });
    return {
      type: 'spam_hidden',
      message: 'Thank you for your message! We\'ll get back to you soon.',
      logReason: 'SUSPICIOUS_REPETITION'
    };
  }
  
  return null; // No spam detected
}

// API endpoint to view recent attacks (for your monitoring)
export const GET = async ({ request }) => {
  // Simple auth check - only allow from localhost or your IP
  const clientIP = getRealIP(request);
  
  // You can add your own IP here for remote monitoring
  const allowedIPs = ['127.0.0.1', '::1', 'localhost'];
  
  if (!allowedIPs.includes(clientIP) && !clientIP.startsWith('10.0.0.')) {
    return new Response('Unauthorized', { status: 401 });
  }
  
  const recentAttacks = attackLog.slice(-50); // Last 50 attacks
  const rateLimitStats = Array.from(rateLimitMap.entries()).map(([ip, userData]) => {
    const now = Date.now();
    const isCurrentlyBlocked = userData.blockedUntil && now < userData.blockedUntil;
    
    return {
      ip,
      requestCount: userData.requests ? userData.requests.length : 0,
      lastRequest: userData.requests && userData.requests.length > 0 
        ? new Date(Math.max(...userData.requests)).toISOString() 
        : null,
      isBlocked: isCurrentlyBlocked,
      blockedUntil: userData.blockedUntil ? new Date(userData.blockedUntil).toISOString() : null,
      remainingBlockTime: isCurrentlyBlocked 
        ? Math.ceil((userData.blockedUntil - now) / 1000 / 60) + ' minutes'
        : null
    };
  });
  
  return new Response(JSON.stringify({
    recentAttacks,
    rateLimitStats,
    totalAttacksLogged: attackLog.length
  }, null, 2), {
    headers: { 'Content-Type': 'application/json' }
  });
};

export const POST = async ({ request }) => {
  try {
    const clientIP = getRealIP(request);
    const userAgent = request.headers.get('user-agent') || 'unknown';
    
    console.log(`Contact form submission from IP: ${clientIP}, UA: ${userAgent}`);
    
    // Check rate limiting
    if (isRateLimited(clientIP)) {
      console.log(`🚫 Rate limit exceeded for IP: ${clientIP}`);
      return new Response(JSON.stringify({ 
        error: 'Too many requests. Please wait before submitting again.' 
      }), { 
        status: 429,
        headers: {
          'Content-Type': 'application/json',
          'Retry-After': '3600' // 1 hour in seconds
        }
      });
    }
    
    // Parse the request body
    let data;
    try {
      data = await request.json();
      console.log('Received form data:', { ...data, website: data.website ? '[FILLED]' : '[EMPTY]' });
    } catch (parseError) {
      logSuspiciousActivity(clientIP, 'INVALID_JSON', { userAgent });
      console.error('Failed to parse request body:', parseError);
      return new Response(JSON.stringify({ 
        error: 'Invalid request format' 
      }), { 
        status: 400,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }
    
    const { name, email, phone, subject, message } = data;
    
    // Validate required fields
    if (!name || !email || !subject || !message) {
      logSuspiciousActivity(clientIP, 'MISSING_REQUIRED_FIELDS', {
        userAgent,
        formData: { name: !!name, email: !!email, subject: !!subject, message: !!message }
      });
      console.log('Missing required fields');
      return new Response(JSON.stringify({ 
        error: 'All required fields must be filled' 
      }), { 
        status: 400,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }

    // Email validation
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(email)) {
      logSuspiciousActivity(clientIP, 'INVALID_EMAIL', {
        userAgent,
        formData: { name, email, subject }
      });
      console.log('Invalid email format:', email);
      return new Response(JSON.stringify({ 
        error: 'Please provide a valid email address' 
      }), { 
        status: 400,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }

    // First check for validation errors
    const validationError = validateMessage(data, clientIP, userAgent);
    if (validationError) {
      const { message: responseMessage, logReason } = validationError;
      
      console.log(`❌ Validation error from ${clientIP}: ${logReason}`);
      return new Response(JSON.stringify({ 
        error: responseMessage 
      }), { 
        status: 400,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }

    // Then check for spam
    const spamResult = detectSpam(data, clientIP, userAgent);
    if (spamResult) {
      const { message: responseMessage, logReason } = spamResult;
      
      console.log(`🚨 Spam detected from ${clientIP}: ${logReason}`);
      return new Response(JSON.stringify({ 
        success: true,
        message: responseMessage
      }), { 
        status: 200,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }

    // Get ntfy configuration from environment variables
    const ntfyUrl = import.meta.env.PUBLIC_NTFY_URL;
    const ntfyToken = import.meta.env.PUBLIC_NTFY_TOKEN;

    console.log('ntfy URL configured:', !!ntfyUrl);
    console.log('ntfy Token configured:', !!ntfyToken);

    if (!ntfyUrl) {
      console.error('ntfy URL not configured');
      return new Response(JSON.stringify({ 
        error: 'Server configuration error' 
      }), { 
        status: 500,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }

    // Format the message in Markdown
    const messageBody = `** Website Contact Form **

${subject}

**Message:**
${message}

**Details:**
**Time:** ${new Date().toISOString()}
**Name:** ${name}
**Email:** ${email}
**Phone:** ${phone || 'Not provided'}
**IP:** ${clientIP}
**User Agent:** ${userAgent}`;

    // Prepare headers with Bearer token authentication
    const headers = {
      'Content-Type': 'text/plain',
      'Title': `Website Contact: ${subject}`,
      'Markdown': 'yes',
      'Tags': 'contact,website'
    };
    
    // Add authentication if token is provided
    if (ntfyToken) {
      headers['Authorization'] = `Bearer ${ntfyToken}`;
    }

    console.log('Sending to ntfy...');
    
    // Send to ntfy
    const response = await fetch(ntfyUrl, {
      method: 'POST',
      headers: headers,
      body: messageBody
    });
    
    console.log('ntfy response status:', response.status);
    
    if (!response.ok) {
      const errorText = await response.text();
      console.error('ntfy error response:', errorText);
      return new Response(JSON.stringify({ 
        error: 'Failed to send message. Please try again later.' 
      }), { 
        status: 500,
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }

    console.log('✅ Legitimate message sent successfully from', clientIP);

    // File logging
    try {
      const fs = await import('fs');
      const path = await import('path');
      
      const logDir = path.default.resolve(process.cwd(), 'logs');
      const logFile = path.default.join(logDir, 'contact-messages.log');
      
      if (!fs.default.existsSync(logDir)) {
        fs.default.mkdirSync(logDir, { recursive: true });
      }
      
      const logMessage = `
=== New Message ${new Date().toISOString()} ===
From: ${name} (${email})
Phone: ${phone || 'Not provided'}
Subject: ${subject}
IP: ${clientIP}
User Agent: ${userAgent}

${message}
==============================
`;
      
      fs.default.appendFileSync(logFile, logMessage);
      console.log('Message logged to file');
    } catch (logError) {
      console.error('Failed to log to file:', logError);
    }
    
    return new Response(JSON.stringify({ 
      success: true,
      message: 'Message sent successfully! We\'ll get back to you soon.'
    }), { 
      status: 200,
      headers: {
        'Content-Type': 'application/json'
      }
    });
  } catch (error) {
    console.error('Unexpected error in contact form:', error);
    return new Response(JSON.stringify({ 
      error: 'Server error occurred. Please try again later.' 
    }), { 
      status: 500,
      headers: {
        'Content-Type': 'application/json'
      }
    });
  }
};
