/**
 * Input validation and sanitization utilities for the Needyfy API.
 */

/**
 * Strip HTML tags from a string to prevent XSS.
 */
export function sanitizeString(input: string): string {
  if (typeof input !== 'string') return '';
  return input
    .replace(/<[^>]*>/g, '') // Remove HTML tags
    .replace(/&/g, '&amp;')  // Encode ampersands
    .replace(/</g, '&lt;')   // Encode less-than
    .replace(/>/g, '&gt;')   // Encode greater-than
    .replace(/"/g, '&quot;') // Encode double quotes
    .replace(/'/g, '&#x27;') // Encode single quotes
    .trim();
}

/**
 * Sanitize a string for display (lighter sanitization that preserves some formatting).
 * Removes script tags and event handlers but allows basic formatting.
 */
export function sanitizeRichText(input: string): string {
  if (typeof input !== 'string') return '';
  return input
    .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '') // Remove script tags
    .replace(/\son\w+\s*=\s*("[^"]*"|'[^']*'|[^\s>]*)/gi, '') // Remove event handlers
    .replace(/javascript:/gi, '') // Remove javascript: URLs
    .trim();
}

/**
 * Validate an email address format.
 */
export function isValidEmail(email: string): boolean {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

/**
 * Validate a password meets minimum requirements.
 */
export function isValidPassword(password: string): { valid: boolean; errors: string[] } {
  const errors: string[] = [];
  if (password.length < 6) errors.push('Password must be at least 6 characters');
  if (password.length > 128) errors.push('Password must be at most 128 characters');
  return { valid: errors.length === 0, errors };
}

/**
 * Validate a name string.
 */
export function isValidName(name: string): boolean {
  if (!name || typeof name !== 'string') return false;
  const trimmed = name.trim();
  return trimmed.length >= 1 && trimmed.length <= 100;
}

/**
 * Validate a phone number (basic validation).
 */
export function isValidPhone(phone: string): boolean {
  if (!phone) return true; // Phone is optional
  const phoneRegex = /^\+?[\d\s-]{7,15}$/;
  return phoneRegex.test(phone);
}

/**
 * Validate pagination parameters.
 */
export function validatePagination(page: unknown, limit: unknown): { page: number; limit: number } {
  const parsedPage = Math.max(1, parseInt(String(page)) || 1);
  const parsedLimit = Math.min(100, Math.max(1, parseInt(String(limit)) || 10));
  return { page: parsedPage, limit: parsedLimit };
}

/**
 * Validate a numeric ID (cuid format).
 */
export function isValidId(id: string): boolean {
  if (!id || typeof id !== 'string') return false;
  return /^[a-zA-Z0-9]{10,}$/.test(id);
}

/**
 * Validate a price/amount value.
 */
export function isValidPrice(price: unknown): boolean {
  const num = Number(price);
  return !isNaN(num) && num >= 0 && num <= 99999999;
}

/**
 * Validate a string length.
 */
export function isValidLength(value: string, min: number, max: number): boolean {
  if (!value || typeof value !== 'string') return false;
  return value.trim().length >= min && value.trim().length <= max;
}

/**
 * Validate listing type for admin endpoints.
 */
export function isValidListingType(type: string): boolean {
  return ['houses', 'shops', 'products'].includes(type);
}

/**
 * Validate order status.
 */
export function isValidOrderStatus(status: string): boolean {
  return ['pending', 'confirmed', 'shipped', 'delivered', 'cancelled'].includes(status);
}

/**
 * Validate MCQ answer option.
 */
export function isValidMcqAnswer(answer: string): boolean {
  return ['A', 'B', 'C', 'D'].includes(answer);
}

/**
 * Validate community post type.
 */
export function isValidPostType(type: string): boolean {
  return ['discussion', 'help', 'suggestion', 'review'].includes(type);
}

/**
 * Validate favourite item type.
 */
export function isValidItemType(type: string): boolean {
  return ['house', 'shop', 'product'].includes(type);
}

/**
 * Validate message type.
 */
export function isValidMessageType(type: string): boolean {
  return ['text', 'image', 'file'].includes(type);
}

/**
 * Sanitize an object by sanitizing all string values.
 */
export function sanitizeObject<T extends Record<string, unknown>>(obj: T, fieldsToSanitize: string[]): T {
  const result = { ...obj };
  for (const field of fieldsToSanitize) {
    if (field in result && typeof result[field] === 'string') {
      (result as Record<string, unknown>)[field] = sanitizeString(result[field] as string);
    }
  }
  return result;
}
