/**
 * Password Policy Configuration
 * Enforces strong password requirements
 */

const PASSWORD_POLICY = {
  minLength: 12,
  maxLength: 128,
  requireUppercase: true,
  requireLowercase: true,
  requireNumbers: true,
  requireSpecialChars: true,
  specialChars: '!@#$%^&*()_+-=[]{}|;:,.<>?',
  preventCommonPasswords: true,
  preventUserInfo: true, // Don't allow username/email in password
  maxRepeatingChars: 3,
  historyCount: 5 // Remember last 5 passwords
};

const ACCOUNT_LOCKOUT = {
  maxFailedAttempts: 5,
  lockoutDuration: 30 * 60 * 1000, // 30 minutes
  resetAfterSuccess: true,
  notifyOnLockout: true
};

const PASSWORD_EXPIRY = {
  enabled: true,
  expiryDays: 90,
  warningDays: 14,
  gracePeriodDays: 7
};

const SESSION_POLICY = {
  maxConcurrentSessions: 3,
  absoluteTimeout: 24 * 60 * 60 * 1000, // 24 hours
  idleTimeout: 2 * 60 * 60 * 1000, // 2 hours
  refreshTokenRotation: true
};

// Common passwords to block (top 100 most common)
const COMMON_PASSWORDS = [
  '123456', 'password', '12345678', 'qwerty', '123456789', '12345', '1234', '111111',
  '1234567', 'dragon', '123123', 'baseball', 'iloveyou', 'trustno1', '1234567890',
  'sunshine', 'master', '123321', '666666', 'photoshop', '1111111', 'princess', 'azerty',
  '000000', 'access', '696969', 'batman', '121212', 'letmein', 'qwertyuiop', 'admin',
  'welcome', 'monkey', 'login', 'abc123', 'starwars', 'shadow', 'ashley', 'football',
  'superman', 'michael', 'ninja', 'mustang', 'password1', 'passw0rd', 'password123'
];

/**
 * Validates password against policy
 * @param {string} password - Password to validate
 * @param {object} userData - User data (username, email) to prevent personal info
 * @returns {object} - {valid: boolean, errors: string[]}
 */
function validatePassword(password, userData = {}) {
  const errors = [];

  // Length check
  if (password.length < PASSWORD_POLICY.minLength) {
    errors.push(`Password must be at least ${PASSWORD_POLICY.minLength} characters long`);
  }
  if (password.length > PASSWORD_POLICY.maxLength) {
    errors.push(`Password must not exceed ${PASSWORD_POLICY.maxLength} characters`);
  }

  // Character requirements
  if (PASSWORD_POLICY.requireUppercase && !/[A-Z]/.test(password)) {
    errors.push('Password must contain at least one uppercase letter');
  }
  if (PASSWORD_POLICY.requireLowercase && !/[a-z]/.test(password)) {
    errors.push('Password must contain at least one lowercase letter');
  }
  if (PASSWORD_POLICY.requireNumbers && !/\d/.test(password)) {
    errors.push('Password must contain at least one number');
  }
  if (PASSWORD_POLICY.requireSpecialChars) {
    const specialCharsRegex = new RegExp(`[${PASSWORD_POLICY.specialChars.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}]`);
    if (!specialCharsRegex.test(password)) {
      errors.push('Password must contain at least one special character (!@#$%^&*...)');
    }
  }

  // Repeating characters
  const repeatingRegex = new RegExp(`(.)\\1{${PASSWORD_POLICY.maxRepeatingChars},}`);
  if (repeatingRegex.test(password)) {
    errors.push(`Password cannot contain more than ${PASSWORD_POLICY.maxRepeatingChars} repeating characters`);
  }

  // Common passwords
  if (PASSWORD_POLICY.preventCommonPasswords) {
    const lowerPassword = password.toLowerCase();
    if (COMMON_PASSWORDS.some(common => lowerPassword.includes(common))) {
      errors.push('Password is too common or easily guessable');
    }
  }

  // User info in password
  if (PASSWORD_POLICY.preventUserInfo && userData) {
    const lowerPassword = password.toLowerCase();
    if (userData.username && lowerPassword.includes(userData.username.toLowerCase())) {
      errors.push('Password cannot contain your username');
    }
    if (userData.email) {
      const emailParts = userData.email.split('@')[0].toLowerCase();
      if (lowerPassword.includes(emailParts)) {
        errors.push('Password cannot contain your email address');
      }
    }
  }

  return {
    valid: errors.length === 0,
    errors,
    strength: calculatePasswordStrength(password)
  };
}

/**
 * Calculate password strength score (0-100)
 */
function calculatePasswordStrength(password) {
  let score = 0;

  // Length score (0-30 points)
  score += Math.min(30, password.length * 2);

  // Character variety (0-40 points)
  if (/[a-z]/.test(password)) score += 10;
  if (/[A-Z]/.test(password)) score += 10;
  if (/\d/.test(password)) score += 10;
  if (/[^a-zA-Z0-9]/.test(password)) score += 10;

  // Patterns (0-30 points)
  const hasNoRepeats = !/(.)\\1{2,}/.test(password);
  const hasNoSequence = !/(?:abc|bcd|cde|123|234|345)/i.test(password);
  const hasMixedCase = /[a-z]/.test(password) && /[A-Z]/.test(password);
  
  if (hasNoRepeats) score += 10;
  if (hasNoSequence) score += 10;
  if (hasMixedCase) score += 10;

  return Math.min(100, score);
}

/**
 * Get password strength label
 */
function getStrengthLabel(score) {
  if (score >= 80) return { label: 'Strong', color: 'success' };
  if (score >= 60) return { label: 'Good', color: 'info' };
  if (score >= 40) return { label: 'Fair', color: 'warning' };
  return { label: 'Weak', color: 'error' };
}

module.exports = {
  PASSWORD_POLICY,
  ACCOUNT_LOCKOUT,
  PASSWORD_EXPIRY,
  SESSION_POLICY,
  validatePassword,
  calculatePasswordStrength,
  getStrengthLabel
};
