/**
 * User Input Validation and Formatting Library
 *
 * Implements the rules defined in docs/input_validation_plan.md.
 * Provides formatting functions and a Zod-integrated pipeline that:
 *   1. Removes disallowed characters
 *   2. Trims leading/trailing whitespace
 *   3. Validates format (email)
 *   4. Applies case transformation
 *   5. Truncates to max length
 */

// ─── Character class definitions ───────────────────────────────

const LETTERS_NUMBERS = 'a-zA-Z0-9'
const LETTERS_NUMBERS_HYPHEN = `${LETTERS_NUMBERS}\\-`
const LETTERS_SPACES_HYPHEN = 'a-zA-Z\\s\\-'
const BASE_TEXT = `${LETTERS_NUMBERS}\\s\\-\\/`
const EXTENDED_TEXT = `${BASE_TEXT},`

// ─── Field type definitions ────────────────────────────────────

export type FieldType =
  | 'name' | 'nationality' | 'streetAddress' | 'city'
  | 'pickupLocation' | 'returnLocation' | 'country'
  | 'fullAddress' | 'commercialName' | 'legalCompanyName'
  | 'email'
  | 'licensePlate' | 'vin' | 'cin' | 'passportNumber'
  | 'internationalPermitNumber' | 'driverLicenseNumber'
  | 'licenseCategory' | 'iceNumber' | 'commercialRegistry'
  | 'carMark' | 'carModel' | 'carColor'
  | 'zipCode'

interface FieldConfig {
  maxLength: number
  allowedPattern: RegExp
  transform: (value: string) => string
}

// ─── Formatting functions ──────────────────────────────────────

/** Uppercase first letter of each word, lowercase the rest */
export function toTitleCase(str: string): string {
  return str.replace(/\b\w+/g, (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
}

/** Uppercase first letter of every word */
export function toTitleCaseAll(str: string): string {
  return str.replace(/\b\w+/g, (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
}

export function toLowerCase(str: string): string {
  return str.toLowerCase()
}

/** Uppercase letters only, leave numbers unchanged */
export function toUpperCase(str: string): string {
  return str.replace(/[a-zA-Z]/g, (char) => char.toUpperCase())
}

export function preserveOriginal(str: string): string {
  return str
}

// ─── Field configuration ───────────────────────────────────────

const FIELD_CONFIGS: Record<FieldType, FieldConfig> = {
  // Group 1: Title Case
  name:           { maxLength: 50,  allowedPattern: new RegExp('^[' + LETTERS_SPACES_HYPHEN + ']*$'),    transform: toTitleCase },
  nationality:    { maxLength: 50,  allowedPattern: new RegExp('^[' + LETTERS_SPACES_HYPHEN + ']*$'),    transform: toTitleCase },
  streetAddress:  { maxLength: 100, allowedPattern: new RegExp('^[' + BASE_TEXT + ']*$'),                transform: toTitleCase },
  city:           { maxLength: 50,  allowedPattern: new RegExp('^[' + LETTERS_SPACES_HYPHEN + ']*$'),    transform: toTitleCase },
  pickupLocation: { maxLength: 50,  allowedPattern: new RegExp('^[' + BASE_TEXT + ']*$'),                transform: toTitleCase },
  returnLocation: { maxLength: 50,  allowedPattern: new RegExp('^[' + BASE_TEXT + ']*$'),                transform: toTitleCase },
  country:        { maxLength: 50,  allowedPattern: new RegExp('^[' + LETTERS_SPACES_HYPHEN + ']*$'),    transform: toTitleCase },

  // Group 2: Title Case All
  fullAddress:      { maxLength: 200, allowedPattern: new RegExp('^[' + EXTENDED_TEXT + ']*$'),           transform: toTitleCaseAll },
  commercialName:   { maxLength: 100, allowedPattern: new RegExp('^[' + EXTENDED_TEXT + ']*$'),           transform: toTitleCaseAll },
  legalCompanyName: { maxLength: 100, allowedPattern: new RegExp('^[' + EXTENDED_TEXT + ']*$'),           transform: toTitleCaseAll },

  // Group 3: Lowercase — email
  email: { maxLength: 100, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS + '@._%\\+\\-]*$'), transform: toLowerCase },

  // Group 4: Uppercase (hyphens allowed per plan examples: "abc-123" → "ABC-123")
  licensePlate:             { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  vin:                      { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  cin:                      { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  passportNumber:           { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  internationalPermitNumber:{ maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  driverLicenseNumber:      { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  licenseCategory:          { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  iceNumber:                { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },
  commercialRegistry:       { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS_HYPHEN + ']*$'), transform: toUpperCase },

  // Group 5: Car fields
  carMark:  { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS + '\\s\\-]*$'), transform: toTitleCase },
  carModel: { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS + '\\s\\-]*$'), transform: toTitleCase },
  carColor: { maxLength: 30, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS + '\\s\\-]*$'), transform: toTitleCase },

  // Group 6: Preserved (spaces for UK postcodes like "SW1A 1AA")
  zipCode: { maxLength: 10, allowedPattern: new RegExp('^[' + LETTERS_NUMBERS + '\\s\\-]*$'), transform: preserveOriginal },
}

// ─── Public API ────────────────────────────────────────────────

/** Full processing pipeline: sanitize → trim → format → truncate */
export function sanitizeAndFormat(value: string, fieldType: FieldType): string {
  const config = FIELD_CONFIGS[fieldType]

  // Step 1: Remove disallowed characters
  let sanitized = ''
  for (const char of value) {
    if (config.allowedPattern.test(char)) {
      sanitized += char
    }
  }

  // Step 2: Trim
  sanitized = sanitized.trim()

  // Step 3: Apply case transformation
  const formatted = config.transform(sanitized)

  // Step 4: Truncate
  if (formatted.length > config.maxLength) {
    return formatted.slice(0, config.maxLength)
  }

  return formatted
}

/** Get the max length for a given field type */
export function getMaxLength(fieldType: FieldType): number {
  return FIELD_CONFIGS[fieldType].maxLength
}
