/**
 * Input validation utilities for security and data integrity
 */

/**
 * Validate Jellyfin item ID format
 * Item IDs should be non-empty alphanumeric strings with optional dashes/underscores
 */
export function validateItemId(itemId: string): void {
  if (!itemId || typeof itemId !== "string") {
    throw new Error("Invalid itemId: must be a non-empty string");
  }

  if (itemId.length > 50) {
    throw new Error("Invalid itemId: exceeds maximum length of 50 characters");
  }

  // Jellyfin item IDs are typically UUIDs or numeric IDs
  if (!/^[a-zA-Z0-9\-_]+$/.test(itemId)) {
    throw new Error("Invalid itemId: contains invalid characters");
  }
}

/**
 * Validate image type to prevent path traversal attacks
 */
export function validateImageType(imageType: string): void {
  if (!imageType || typeof imageType !== "string") {
    throw new Error("Invalid imageType: must be a non-empty string");
  }

  // Only allow known image types
  const validImageTypes = [
    "Primary",
    "Backdrop",
    "Banner",
    "Disc",
    "Box",
    "Logo",
    "Thumb",
    "Art",
    "Chapter",
    "Keyframe",
  ];

  if (!validImageTypes.includes(imageType)) {
    throw new Error(`Invalid imageType: "${imageType}" is not a valid image type`);
  }
}

/**
 * Validate media source ID format
 */
export function validateMediaSourceId(mediaSourceId: string): void {
  if (!mediaSourceId || typeof mediaSourceId !== "string") {
    throw new Error("Invalid mediaSourceId: must be a non-empty string");
  }

  if (mediaSourceId.length > 50) {
    throw new Error("Invalid mediaSourceId: exceeds maximum length");
  }

  if (!/^[a-zA-Z0-9\-_]+$/.test(mediaSourceId)) {
    throw new Error("Invalid mediaSourceId: contains invalid characters");
  }
}

/**
 * Validate URL path segment to prevent directory traversal
 * Disallows: "..", ".", and characters that could enable attacks
 */
export function validateUrlPathSegment(segment: string): void {
  if (!segment || typeof segment !== "string") {
    throw new Error("Invalid path segment: must be a non-empty string");
  }

  if (segment === ".." || segment === ".") {
    throw new Error("Invalid path segment: directory traversal not allowed");
  }

  // Reject path separators and null bytes
  if (/[\/\\%]/.test(segment)) {
    throw new Error("Invalid path segment: contains invalid characters");
  }
}

/**
 * Validate numeric parameter (width, height, quality, etc.)
 */
export function validateNumericParam(value: unknown, min = 0, max = 10000, name = "parameter"): number {
  // Must be an actual number, not a string that looks like a number
  if (typeof value !== "number") {
    throw new Error(`Invalid ${name}: must be an integer`);
  }

  if (!Number.isInteger(value)) {
    throw new Error(`Invalid ${name}: must be an integer`);
  }

  if (value < min || value > max) {
    throw new Error(`Invalid ${name}: must be between ${min} and ${max}`);
  }

  return value;
}

/**
 * Sanitize query parameter value - allows alphanumeric, dash, underscore
 */
export function validateQueryParamValue(value: string, maxLength = 100): void {
  if (typeof value !== "string") {
    throw new Error("Query parameter value must be a string");
  }

  if (value.length > maxLength) {
    throw new Error(`Query parameter exceeds maximum length of ${maxLength}`);
  }

  // Allow only safe characters in query params
  if (!/^[a-zA-Z0-9\-_.~]+$/.test(value)) {
    throw new Error("Query parameter contains invalid characters");
  }
}
