/**
 * @copyright 2026 NHCarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */

/**
 * Validates that a URL is a proper base64 data string.
 * Allows whitespace in the base64 data which may occur during transmission.
 */
export function validateDataUrl(url: string): boolean {
  return /^data:image\/(jpeg|png|gif|webp|svg\+xml);base64,[A-Za-z0-9+/=\s]+$/.test(url);
}

/**
 * Validates that a URL is safe and points to an allowed protocol.
 * Prevents javascript:, data:, vbscript:, and file: URLs.
 */
export function validateUrl(url: string): boolean {
  if (!url) {
    return true; // Empty URLs are acceptable for optional fields
  }

  // Check for dangerous protocols
  const dangerousProtocols = /^(javascript|data|vbscript|file):/i;
  if (dangerousProtocols.test(url)) {
    return false;
  }

  // Must be a valid URL format
  try {
    const parsedUrl = new URL(url);
    // Only allow http and https protocols
    if (!["http:", "https:"].includes(parsedUrl.protocol)) {
      return false;
    }
    return true;
  } catch {
    return false;
  }
}

/**
 * Validates string length is within acceptable bounds.
 */
export function validateStringLength(
  value: string | undefined,
  maxLength: number
): boolean {
  if (!value) {
    return true;
  }
  return value.length <= maxLength;
}

/**
 * Validates that a slug contains only safe characters (alphanumeric, hyphens, underscores).
 */
export function validateSlug(slug: string | undefined): boolean {
  if (!slug) {
    return true;
  }
  // Allow alphanumeric, hyphens, underscores only
  const slugPattern = /^[a-z0-9-_]+$/i;
  return slugPattern.test(slug) && slug.length <= 50;
}

/**
 * Validates rating is within acceptable range.
 */
export function validateRating(rating: number | undefined): boolean {
  if (rating === undefined) {
    return true;
  }
  return Number.isInteger(rating) && rating >= 0 && rating <= 10;
}

/**
 * Maximum string lengths for various fields.
 */
export const MAX_LENGTHS = {
  TITLE: 500,
  AUTHOR: 200,
  DESCRIPTION: 5000,
  BIO: 1000,
  SLUG: 50,
  URL: 2048,
  DISPLAY_NAME: 100,
  USERNAME: 100,
  COMMENT_CONTENT: 10000,
  NOTES: 5000,
  TAGS: 50, // per tag
  ISBN: 50,
  DATA_URL: 5 * 1024 * 1024, // 5MB in bytes (not chars)
} as const;
