// Lightweight spam detection and input sanitization

const MAX_NAME_LENGTH = 60;
const MAX_MESSAGE_LENGTH = 1000;
const MAX_WEBSITE_LENGTH = 200;

// Patterns that strongly suggest spam
const SPAM_PATTERNS = [
  /\b(viagra|cialis|casino|poker|lottery|bitcoin|crypto|investment|forex)\b/i,
  /\b(click here|buy now|free money|earn \$|make money)\b/i,
  /(https?:\/\/[^\s]{0,10}){3,}/i, // 3+ URLs in message
];

// Basic URL validation for the optional website field
const SAFE_URL_PATTERN = /^https?:\/\/[a-z0-9-]+(\.[a-z0-9-]+)+(\/[^\s]*)?$/i;

export interface ValidationError {
  field: string;
  message: string;
}

export function sanitizeText(input: string): string {
  // Normalize whitespace: collapse runs of spaces/tabs, normalize line endings
  return input
    .replace(/\r\n/g, '\n')
    .replace(/\r/g, '\n')
    .replace(/[ \t]+/g, ' ')
    .replace(/\n{3,}/g, '\n\n')
    .trim();
}

export function stripHtml(input: string): string {
  // Remove anything that looks like an HTML tag
  return input.replace(/<[^>]*>/g, '').replace(/&[a-z#0-9]+;/gi, (match) => {
    const entities: Record<string, string> = {
      '&amp;': '&',
      '&lt;': '<',
      '&gt;': '>',
      '&quot;': '"',
      '&#39;': "'",
    };
    return entities[match] ?? match;
  });
}

export function validateWebsite(url: string): string | null {
  if (!url || url.trim() === '') return null;

  const cleaned = url.trim();

  if (cleaned.length > MAX_WEBSITE_LENGTH) return null;
  if (!SAFE_URL_PATTERN.test(cleaned)) return null;

  // Block localhost and private ranges in URLs
  if (/localhost|127\.|192\.168\.|10\.|172\.(1[6-9]|2\d|3[01])\./i.test(cleaned)) return null;

  return cleaned;
}

export function validateEntry(data: {
  display_name: string;
  message: string;
  website: string;
  consent: string;
  honeypot: string;
}): ValidationError[] {
  const errors: ValidationError[] = [];

  // Honeypot check: must be empty (bots fill it in)
  if (data.honeypot && data.honeypot.trim() !== '') {
    errors.push({ field: 'honeypot', message: 'Spam detected' });
    return errors;
  }

  // Consent required
  if (!data.consent || data.consent !== 'yes') {
    errors.push({ field: 'consent', message: 'You must consent to public posting' });
  }

  // Display name validation
  const name = stripHtml(sanitizeText(data.display_name));
  if (!name || name.length < 1) {
    errors.push({ field: 'display_name', message: 'Please enter a display name' });
  } else if (name.length > MAX_NAME_LENGTH) {
    errors.push({ field: 'display_name', message: `Name must be ${MAX_NAME_LENGTH} characters or less` });
  }

  // Message validation
  const message = stripHtml(sanitizeText(data.message));
  if (!message || message.length < 1) {
    errors.push({ field: 'message', message: 'Please enter a message' });
  } else if (message.length > MAX_MESSAGE_LENGTH) {
    errors.push({ field: 'message', message: `Message must be ${MAX_MESSAGE_LENGTH} characters or less` });
  }

  return errors;
}

export function scoreSpam(data: { display_name: string; message: string; website: string | null }): number {
  let score = 0;
  const combined = `${data.display_name} ${data.message} ${data.website ?? ''}`;

  for (const pattern of SPAM_PATTERNS) {
    if (pattern.test(combined)) score += 30;
  }

  // Lots of URLs in message is suspicious
  const urlCount = (data.message.match(/https?:\/\//gi) ?? []).length;
  if (urlCount >= 2) score += 20 * urlCount;

  // All-caps message is a mild spam signal
  const upperRatio = (data.message.match(/[A-Z]/g) ?? []).length / Math.max(data.message.length, 1);
  if (upperRatio > 0.6 && data.message.length > 10) score += 15;

  return score;
}

export function isLikelySpam(data: { display_name: string; message: string; website: string | null }): boolean {
  return scoreSpam(data) >= 50;
}
