/**
 * Password Validator - 비밀번호 정책 검증
 *
 * 강력한 비밀번호 정책:
 * - 최소 12자 이상
 * - 대문자 포함
 * - 소문자 포함
 * - 숫자 포함
 * - 특수문자 포함
 *
 * @author TK-FB-Project
 * @since 2026-02-04
 */

/**
 * 비밀번호 강도 검증
 *
 * @param {string} password - 검증할 비밀번호
 * @param {Object} options - 옵션 (기본값 사용 권장)
 * @returns {Object} { valid: boolean, errors: string[], strength: string }
 */
const validatePassword = (password, options = {}) => {
  const config = {
    minLength: options.minLength || 12,
    requireUppercase: options.requireUppercase !== false,
    requireLowercase: options.requireLowercase !== false,
    requireNumbers: options.requireNumbers !== false,
    requireSpecialChars: options.requireSpecialChars !== false,
    maxLength: options.maxLength || 128
  };

  const errors = [];
  let strength = 0;

  // 필수 검증
  if (!password || typeof password !== 'string') {
    return {
      valid: false,
      errors: ['비밀번호를 입력해주세요.'],
      strength: 'invalid'
    };
  }

  // 길이 검증
  if (password.length < config.minLength) {
    errors.push(`비밀번호는 최소 ${config.minLength}자 이상이어야 합니다.`);
  } else {
    strength += 1;
  }

  if (password.length > config.maxLength) {
    errors.push(`비밀번호는 ${config.maxLength}자를 초과할 수 없습니다.`);
  }

  // 대문자 검증
  if (config.requireUppercase && !/[A-Z]/.test(password)) {
    errors.push('대문자를 1개 이상 포함해야 합니다.');
  } else if (/[A-Z]/.test(password)) {
    strength += 1;
  }

  // 소문자 검증
  if (config.requireLowercase && !/[a-z]/.test(password)) {
    errors.push('소문자를 1개 이상 포함해야 합니다.');
  } else if (/[a-z]/.test(password)) {
    strength += 1;
  }

  // 숫자 검증
  if (config.requireNumbers && !/\d/.test(password)) {
    errors.push('숫자를 1개 이상 포함해야 합니다.');
  } else if (/\d/.test(password)) {
    strength += 1;
  }

  // 특수문자 검증
  const specialChars = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/;
  if (config.requireSpecialChars && !specialChars.test(password)) {
    errors.push('특수문자를 1개 이상 포함해야 합니다. (!@#$%^&*()_+-=[]{};\':"|,.<>/?)');
  } else if (specialChars.test(password)) {
    strength += 1;
  }

  // 공백 검증
  if (/\s/.test(password)) {
    errors.push('비밀번호에 공백을 포함할 수 없습니다.');
  }

  // 연속된 문자 검증 (선택적)
  if (/(.)\1{2,}/.test(password)) {
    errors.push('동일한 문자를 3회 이상 연속 사용할 수 없습니다.');
  }

  // 강도 계산
  let strengthLabel;
  if (strength <= 2) {
    strengthLabel = 'weak';
  } else if (strength <= 3) {
    strengthLabel = 'medium';
  } else if (strength <= 4) {
    strengthLabel = 'strong';
  } else {
    strengthLabel = 'very_strong';
  }

  return {
    valid: errors.length === 0,
    errors,
    strength: strengthLabel,
    score: strength
  };
};

/**
 * 간단한 비밀번호 검증 (기존 호환용)
 * 모든 조건을 만족하면 true, 아니면 false
 *
 * @param {string} password - 검증할 비밀번호
 * @returns {boolean} 유효 여부
 */
const isValidPassword = (password) => {
  return validatePassword(password).valid;
};

/**
 * 비밀번호 검증 결과를 한국어 메시지로 반환
 *
 * @param {string} password - 검증할 비밀번호
 * @returns {string|null} 오류 메시지 (유효하면 null)
 */
const getPasswordError = (password) => {
  const result = validatePassword(password);
  if (result.valid) {
    return null;
  }
  return result.errors.join(' ');
};

/**
 * Express 미들웨어: 요청 body의 password 또는 newPassword 필드 검증
 *
 * @param {string} fieldName - 검증할 필드명 (기본: 'password')
 * @returns {Function} Express 미들웨어
 */
const validatePasswordMiddleware = (fieldName = 'password') => {
  return (req, res, next) => {
    const password = req.body[fieldName] || req.body.newPassword;

    if (!password) {
      return next(); // 비밀번호 필드가 없으면 다음 미들웨어로
    }

    const result = validatePassword(password);

    if (!result.valid) {
      return res.status(400).json({
        success: false,
        error: '비밀번호가 보안 요구사항을 충족하지 않습니다.',
        details: result.errors,
        code: 'WEAK_PASSWORD'
      });
    }

    next();
  };
};

module.exports = {
  validatePassword,
  isValidPassword,
  getPasswordError,
  validatePasswordMiddleware
};
