/**
 * Form Validation Utilities
 * Reusable validation functions for auth forms and other components
 */

/**
 * Validate email format - requires valid domain with 2+ char TLD
 * @param email - Email address to validate
 * @returns true if email is valid
 */
export function isValidEmail(email: string): boolean {
  const trimmed = email.trim();
  // Regex requires: user@domain.TLD (TLD must be 2+ chars)
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
  return emailRegex.test(trimmed);
}

/**
 * Validate name format - letters, spaces, hyphens, apostrophes only
 * @param name - Name to validate
 * @param minLength - Minimum length (default: 2)
 * @param maxLength - Maximum length (default: 50)
 * @returns true if name is valid
 */
export function isValidName(name: string, minLength = 2, maxLength = 50): boolean {
  const trimmed = name.trim();
  if (trimmed.length < minLength || trimmed.length > maxLength) {
    return false;
  }
  // Allow letters, spaces, hyphens, and apostrophes
  const nameRegex = /^[a-zA-Z\s\-']+$/;
  return nameRegex.test(trimmed);
}

/**
 * Password strength check
 * @param password - Password to check
 * @param confirmPassword - Confirmation password (optional)
 * @returns Object with individual check results
 */
export interface PasswordChecks {
  minLength: boolean;      // 8+ characters
  uppercase: boolean;      // At least one A-Z
  lowercase: boolean;      // At least one a-z
  number: boolean;         // At least one 0-9
  special: boolean;        // At least one special character
  match: boolean;          // Matches confirmation password
}

export function checkPasswordStrength(
  password: string,
  confirmPassword?: string
): PasswordChecks {
  return {
    minLength: password.length >= 8,
    uppercase: /[A-Z]/.test(password),
    lowercase: /[a-z]/.test(password),
    number: /[0-9]/.test(password),
    special: /[^A-Za-z0-9]/.test(password),
    match: confirmPassword ? password === confirmPassword : true,
  };
}

/**
 * Check if password is strong (all requirements met)
 * @param checks - PasswordChecks object
 * @returns true if all checks pass
 */
export function isPasswordStrong(checks: PasswordChecks): boolean {
  return (
    checks.minLength &&
    checks.uppercase &&
    checks.lowercase &&
    checks.number &&
    checks.special &&
    checks.match
  );
}

/**
 * Validate that a CAPTCHA answer was entered.
 *
 * NOTE: The captcha challenge itself (arithmetic question) is generated and
 * verified server-side (POST /api/auth/captcha, then captcha_id +
 * captcha_answer sent with register/login). The client can no longer check
 * correctness — it only guards against submitting with an empty answer.
 */
export function isValidCaptcha(input: string): boolean {
  return input.trim().length > 0;
}

/**
 * Validate Indian mobile phone number (10 digits, starts with 6-9)
 * Allows optional +91 or 0 prefix
 */
export function isValidPhone(phone: string): boolean {
  const cleaned = phone.trim().replace(/[\s\-()]/g, '');
  if (!cleaned) return false;
  // Strip +91 or 91 or 0 prefix
  const normalized = cleaned.replace(/^(\+91|91|0)/, '');
  return /^[6-9]\d{9}$/.test(normalized);
}

/**
 * Validate a URL (http or https)
 * @param url - URL string to validate
 * @returns true if URL is valid
 */
export function isValidURL(url: string): boolean {
  const trimmed = url.trim();
  if (!trimmed) return false;
  try {
    const parsed = new URL(trimmed);
    return parsed.protocol === "http:" || parsed.protocol === "https:";
  } catch {
    return false;
  }
}

/**
 * Validate a title or short text field (letters, numbers, common punctuation)
 */
export function isValidTitle(text: string, minLen = 3, maxLen = 200): boolean {
  const trimmed = text.trim();
  return trimmed.length >= minLen && trimmed.length <= maxLen;
}

/**
 * Validate a description / long text field
 */
export function isValidDescription(text: string, minLen = 20, maxLen = 5000): boolean {
  const trimmed = text.trim();
  return trimmed.length >= minLen && trimmed.length <= maxLen;
}

/**
 * Validate a location string (at least 2 chars)
 */
export function isValidLocation(loc: string, minLen = 2, maxLen = 255): boolean {
  const trimmed = loc.trim();
  return trimmed.length >= minLen && trimmed.length <= maxLen;
}

/**
 * Validate a price (positive number, up to reasonable max)
 */
export function isValidPrice(value: string | number): boolean {
  const n = typeof value === 'string' ? parseFloat(value) : value;
  return !isNaN(n) && n > 0 && n <= 10_000_000;
}

/**
 * Validate a budget string (optional — empty is valid; if filled must be positive integer)
 */
export function isValidBudget(budget: string): boolean {
  if (!budget.trim()) return true; // optional
  const n = parseInt(budget, 10);
  return !isNaN(n) && n > 0 && n <= 100_000_000;
}

/**
 * Validate salary range — both optional, but if both filled min must be < max
 */
export function isValidSalaryRange(min: string, max: string): boolean {
  if (!min && !max) return true;
  if (min && !max) return parseFloat(min) > 0;
  if (!min && max) return parseFloat(max) > 0;
  return parseFloat(min) > 0 && parseFloat(max) > 0 && parseFloat(min) <= parseFloat(max);
}

/**
 * Validate duration in minutes (optional — empty is valid; if filled must be positive integer)
 */
export function isValidDuration(minutes: string): boolean {
  if (!minutes.trim()) return true; // optional
  const n = parseInt(minutes, 10);
  return !isNaN(n) && n > 0 && n <= 1440; // max 24h
}

/**
 * Validate comma-separated tags (each tag 1-40 chars, max 20 tags)
 */
export function isValidTags(tags: string): boolean {
  if (!tags.trim()) return true; // optional
  const parts = tags.split(',').map((t) => t.trim()).filter(Boolean);
  if (parts.length > 20) return false;
  return parts.every((t) => t.length >= 1 && t.length <= 40);
}

/**
 * Validate full name (letters, spaces, hyphens, apostrophes; 2-100 chars)
 */
export function isValidFullName(name: string): boolean {
  return isValidName(name, 2, 100);
}

/**
 * Get user-friendly error message for validation failure
 * @param fieldName - Name of the field
 * @param validationType - Type of validation that failed
 * @returns User-friendly error message
 */
export function getValidationErrorMessage(fieldName: string, validationType: string): string {
  const messages: Record<string, Record<string, string>> = {
    email: {
      invalid: 'Please enter a valid email address with a domain (e.g., user@example.com)',
      required: 'Email address is required',
    },
    firstName: {
      invalid: 'First name must be 2-50 characters and contain only letters, spaces, hyphens, or apostrophes',
      required: 'First name is required',
      tooShort: 'First name must be at least 2 characters',
      tooLong: 'First name must not exceed 50 characters',
    },
    lastName: {
      invalid: 'Last name must be 2-50 characters and contain only letters, spaces, hyphens, or apostrophes',
      required: 'Last name is required',
      tooShort: 'Last name must be at least 2 characters',
      tooLong: 'Last name must not exceed 50 characters',
    },
    fullName: {
      invalid: 'Full name must be 2-50 characters and contain only letters, spaces, hyphens, or apostrophes',
      required: 'Full name is required',
    },
    password: {
      required: 'Password is required',
      weak: 'Password must contain: 8+ characters, uppercase, lowercase, number, and special character',
      tooShort: 'Password must be at least 8 characters',
      noUppercase: 'Password must contain at least one uppercase letter',
      noLowercase: 'Password must contain at least one lowercase letter',
      noNumber: 'Password must contain at least one number',
      noSpecial: 'Password must contain at least one special character',
    },
    confirmPassword: {
      required: 'Please confirm your password',
      noMatch: 'Passwords do not match',
    },
    captcha: {
      required: 'Captcha is required',
      invalid: 'Captcha does not match. Please try again.',
    },
    terms: {
      required: 'You must agree to the Terms and Privacy Policy to continue',
    },
  };

  return messages[fieldName]?.[validationType] ?? 'Invalid input';
}

/**
 * Validate entire register form
 * @param formData - Object with form field values
 * @returns Object with validation results and errors
 */
export interface RegisterFormData {
  firstName: string;
  lastName: string;
  email: string;
  password: string;
  confirmPassword: string;
  captcha: string;
  termsAccepted: boolean;
}

export interface ValidationResult {
  isValid: boolean;
  errors: Record<string, string>;
}

export function validateRegisterForm(formData: RegisterFormData): ValidationResult {
  const errors: Record<string, string> = {};

  // Validate first name
  if (!formData.firstName.trim()) {
    errors.firstName = getValidationErrorMessage('firstName', 'required');
  } else if (!isValidName(formData.firstName, 2, 50)) {
    errors.firstName = getValidationErrorMessage('firstName', 'invalid');
  }

  // Validate last name
  if (!formData.lastName.trim()) {
    errors.lastName = getValidationErrorMessage('lastName', 'required');
  } else if (!isValidName(formData.lastName, 2, 50)) {
    errors.lastName = getValidationErrorMessage('lastName', 'invalid');
  }

  // Validate email
  if (!formData.email.trim()) {
    errors.email = getValidationErrorMessage('email', 'required');
  } else if (!isValidEmail(formData.email)) {
    errors.email = getValidationErrorMessage('email', 'invalid');
  }

  // Validate password
  const passwordChecks = checkPasswordStrength(formData.password, formData.confirmPassword);
  if (!formData.password) {
    errors.password = getValidationErrorMessage('password', 'required');
  } else if (!isPasswordStrong(passwordChecks)) {
    errors.password = getValidationErrorMessage('password', 'weak');
  }

  // Validate confirm password
  if (!formData.confirmPassword) {
    errors.confirmPassword = getValidationErrorMessage('confirmPassword', 'required');
  } else if (!passwordChecks.match) {
    errors.confirmPassword = getValidationErrorMessage('confirmPassword', 'noMatch');
  }

  // Validate captcha — correctness is verified server-side; only require an answer.
  if (!isValidCaptcha(formData.captcha)) {
    errors.captcha = getValidationErrorMessage('captcha', 'required');
  }

  // Validate terms acceptance
  if (!formData.termsAccepted) {
    errors.terms = getValidationErrorMessage('terms', 'required');
  }

  return {
    isValid: Object.keys(errors).length === 0,
    errors,
  };
}
