// utils/validator.js - 유효성 검사 유틸리티

const { handleValidationError } = require('./errorHandler');

/**
 * 필수 필드 검사
 */
const required = (value, fieldName) => {
  if (value === undefined || value === null || value === '') {
    handleValidationError(fieldName, value, 'required');
  }
  return true;
};

/**
 * 문자열 길이 검사
 */
const stringLength = (value, fieldName, min = 0, max = Infinity) => {
  if (typeof value !== 'string') {
    handleValidationError(fieldName, value, 'string type');
  }
  if (value.length < min || value.length > max) {
    handleValidationError(fieldName, value, `length between ${min} and ${max}`);
  }
  return true;
};

/**
 * 숫자 범위 검사
 */
const numberRange = (value, fieldName, min = -Infinity, max = Infinity) => {
  const num = parseFloat(value);
  if (isNaN(num)) {
    handleValidationError(fieldName, value, 'number type');
  }
  if (num < min || num > max) {
    handleValidationError(fieldName, value, `number between ${min} and ${max}`);
  }
  return true;
};

/**
 * 정수 검사
 */
const integer = (value, fieldName) => {
  const num = parseInt(value);
  if (isNaN(num) || num.toString() !== value.toString()) {
    handleValidationError(fieldName, value, 'integer');
  }
  return true;
};

/**
 * 이메일 형식 검사
 */
const email = (value, fieldName) => {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!emailRegex.test(value)) {
    handleValidationError(fieldName, value, 'valid email format');
  }
  return true;
};

/**
 * 날짜 형식 검사 (YYYY-MM-DD)
 */
const dateFormat = (value, fieldName) => {
  const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
  if (!dateRegex.test(value)) {
    handleValidationError(fieldName, value, 'YYYY-MM-DD format');
  }
  
  const date = new Date(value);
  if (isNaN(date.getTime())) {
    handleValidationError(fieldName, value, 'valid date');
  }
  return true;
};

/**
 * 시간 형식 검사 (HH:MM)
 */
const timeFormat = (value, fieldName) => {
  const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/;
  if (!timeRegex.test(value)) {
    handleValidationError(fieldName, value, 'HH:MM format');
  }
  return true;
};

/**
 * 열거형 값 검사
 */
const enumValue = (value, fieldName, allowedValues) => {
  if (!allowedValues.includes(value)) {
    handleValidationError(fieldName, value, `one of: ${allowedValues.join(', ')}`);
  }
  return true;
};

/**
 * 배열 검사
 */
const arrayType = (value, fieldName, minLength = 0, maxLength = Infinity) => {
  if (!Array.isArray(value)) {
    handleValidationError(fieldName, value, 'array type');
  }
  if (value.length < minLength || value.length > maxLength) {
    handleValidationError(fieldName, value, `array length between ${minLength} and ${maxLength}`);
  }
  return true;
};

/**
 * 객체 검사
 */
const objectType = (value, fieldName) => {
  if (typeof value !== 'object' || value === null || Array.isArray(value)) {
    handleValidationError(fieldName, value, 'object type');
  }
  return true;
};

/**
 * 비밀번호 강도 검사
 */
const passwordStrength = (value, fieldName) => {
  if (typeof value !== 'string') {
    handleValidationError(fieldName, value, 'string type');
  }
  
  const minLength = 8;
  const hasUpperCase = /[A-Z]/.test(value);
  const hasLowerCase = /[a-z]/.test(value);
  const hasNumbers = /\d/.test(value);
  const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value);
  
  if (value.length < minLength) {
    handleValidationError(fieldName, value, `minimum ${minLength} characters`);
  }
  
  const strengthChecks = [hasUpperCase, hasLowerCase, hasNumbers, hasSpecialChar];
  const passedChecks = strengthChecks.filter(Boolean).length;
  
  if (passedChecks < 3) {
    handleValidationError(fieldName, value, 'at least 3 of: uppercase, lowercase, numbers, special characters');
  }
  
  return true;
};

/**
 * 스키마 기반 유효성 검사
 */
const validateSchema = (data, schema) => {
  const errors = [];
  
  for (const [field, rules] of Object.entries(schema)) {
    const value = data[field];
    
    try {
      // 필수 필드 검사
      if (rules.required) {
        required(value, field);
      }
      
      // 값이 없고 필수가 아니면 다른 검사 스킵
      if ((value === undefined || value === null || value === '') && !rules.required) {
        continue;
      }
      
      // 타입별 검사
      if (rules.type === 'string' && rules.minLength !== undefined && rules.maxLength !== undefined) {
        stringLength(value, field, rules.minLength, rules.maxLength);
      }
      
      if (rules.type === 'number' && rules.min !== undefined && rules.max !== undefined) {
        numberRange(value, field, rules.min, rules.max);
      }
      
      if (rules.type === 'integer') {
        integer(value, field);
      }
      
      if (rules.type === 'email') {
        email(value, field);
      }
      
      if (rules.type === 'date') {
        dateFormat(value, field);
      }
      
      if (rules.type === 'time') {
        timeFormat(value, field);
      }
      
      if (rules.type === 'array') {
        arrayType(value, field, rules.minLength, rules.maxLength);
      }
      
      if (rules.type === 'object') {
        objectType(value, field);
      }
      
      if (rules.enum) {
        enumValue(value, field, rules.enum);
      }
      
      if (rules.password) {
        passwordStrength(value, field);
      }
      
      // 커스텀 검증 함수
      if (rules.custom && typeof rules.custom === 'function') {
        rules.custom(value, field);
      }
      
    } catch (error) {
      errors.push({
        field,
        value,
        message: error.message
      });
    }
  }
  
  if (errors.length > 0) {
    const errorMessage = errors.map(e => `${e.field}: ${e.message}`).join(', ');
    handleValidationError('validation', 'multiple fields', errorMessage);
  }
  
  return true;
};

/**
 * 일반적인 스키마 정의들
 */
const schemas = {
  // 사용자 생성
  createUser: {
    username: { required: true, type: 'string', minLength: 3, maxLength: 50 },
    password: { required: true, password: true },
    name: { required: true, type: 'string', minLength: 2, maxLength: 100 },
    access_level: { required: true, enum: ['user', 'admin', 'system'] },
    user_id: { type: 'integer' }
  },
  
  // 사용자 업데이트
  updateUser: {
    name: { type: 'string', minLength: 2, maxLength: 100 },
    access_level: { enum: ['user', 'admin', 'system'] },
    user_id: { type: 'integer' }
  },
  
  // 비밀번호 변경
  changePassword: {
    currentPassword: { required: true, type: 'string' },
    newPassword: { required: true, password: true }
  },
  
  // 일일 작업 보고서 생성 (배열 형태)
  createDailyWorkReport: {
    report_date: { required: true, type: 'date' },
    user_id: { required: true, type: 'integer' },
    work_entries: { required: true, type: 'array' },
    created_by: { type: 'integer' }
  },
  
  // 프로젝트 생성
  createProject: {
    project_name: { required: true, type: 'string', minLength: 2, maxLength: 200 },
    description: { type: 'string', maxLength: 1000 },
    start_date: { type: 'date' },
    end_date: { type: 'date' }
  },
  
  // 작업자 생성
  createWorker: {
    worker_name: { required: true, type: 'string', minLength: 2, maxLength: 100 },
    position: { type: 'string', maxLength: 100 },
    department: { type: 'string', maxLength: 100 },
    phone: { type: 'string', maxLength: 20 },
    email: { type: 'email' }
  }
};

module.exports = {
  // 개별 검증 함수들
  required,
  stringLength,
  numberRange,
  integer,
  email,
  dateFormat,
  timeFormat,
  enumValue,
  arrayType,
  objectType,
  passwordStrength,
  
  // 스키마 검증
  validateSchema,
  schemas
};
