/**
 * Validation Utilities
 * バリデーション関数
 */

/**
 * メールアドレスの検証
 * @param {string} email メールアドレス
 * @return {boolean}
 */
export function isValidEmail( email ) {
	const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
	return emailRegex.test( email );
}

/**
 * URLの検証
 * @param {string} url URL
 * @return {boolean}
 */
export function isValidUrl( url ) {
	try {
		new URL( url );
		return true;
	} catch {
		return false;
	}
}

/**
 * 電話番号の検証（日本）
 * @param {string} phone 電話番号
 * @return {boolean}
 */
export function isValidPhoneJP( phone ) {
	// ハイフンありなし両方対応
	const phoneRegex = /^(0\d{1,4}-?\d{1,4}-?\d{4}|0\d{9,10})$/;
	return phoneRegex.test( phone.replace( /[^\d-]/g, '' ) );
}

/**
 * 郵便番号の検証（日本）
 * @param {string} zip 郵便番号
 * @return {boolean}
 */
export function isValidZipJP( zip ) {
	const zipRegex = /^\d{3}-?\d{4}$/;
	return zipRegex.test( zip );
}

/**
 * 数値の検証
 * @param {*} value 検証する値
 * @return {boolean}
 */
export function isNumeric( value ) {
	return ! isNaN( parseFloat( value ) ) && isFinite( value );
}

/**
 * 整数の検証
 * @param {*} value 検証する値
 * @return {boolean}
 */
export function isInteger( value ) {
	return Number.isInteger( Number( value ) );
}

/**
 * 範囲内の検証
 * @param {number} value 検証する値
 * @param {number} min   最小値
 * @param {number} max   最大値
 * @return {boolean}
 */
export function isInRange( value, min, max ) {
	const num = Number( value );
	return ! isNaN( num ) && num >= min && num <= max;
}

/**
 * 文字列長の検証
 * @param {string} str 検証する文字列
 * @param {number} min 最小長
 * @param {number} max 最大長
 * @return {boolean}
 */
export function isValidLength( str, min, max ) {
	const length = str.length;
	return length >= min && length <= max;
}

/**
 * 空でないことの検証
 * @param {*} value 検証する値
 * @return {boolean}
 */
export function isNotEmpty( value ) {
	if ( value === null || value === undefined ) {
		return false;
	}
	if ( typeof value === 'string' ) {
		return value.trim().length > 0;
	}
	if ( Array.isArray( value ) ) {
		return value.length > 0;
	}
	if ( typeof value === 'object' ) {
		return Object.keys( value ).length > 0;
	}
	return true;
}

/**
 * 日付の検証
 * @param {string} dateString 日付文字列
 * @return {boolean}
 */
export function isValidDate( dateString ) {
	const date = new Date( dateString );
	return date instanceof Date && ! isNaN( date.getTime() );
}

/**
 * カラーコードの検証（HEX）
 * @param {string} color カラーコード
 * @return {boolean}
 */
export function isValidHexColor( color ) {
	const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
	return hexRegex.test( color );
}

/**
 * パスワード強度の検証
 * @param {string} password パスワード
 * @return {Object} {isValid, strength, message}
 */
export function validatePasswordStrength( password ) {
	const minLength = 8;
	const hasUpperCase = /[A-Z]/.test( password );
	const hasLowerCase = /[a-z]/.test( password );
	const hasNumbers = /\d/.test( password );
	const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test( password );

	let strength = 0;
	let message = '';

	if ( password.length >= minLength ) {
		strength++;
	}
	if ( hasUpperCase ) {
		strength++;
	}
	if ( hasLowerCase ) {
		strength++;
	}
	if ( hasNumbers ) {
		strength++;
	}
	if ( hasSpecialChar ) {
		strength++;
	}

	if ( strength < 2 ) {
		message = '弱いパスワードです';
	} else if ( strength < 4 ) {
		message = '普通のパスワードです';
	} else {
		message = '強いパスワードです';
	}

	return {
		isValid: strength >= 3,
		strength,
		message,
	};
}

/**
 * クレジットカード番号の検証（Luhnアルゴリズム）
 * @param {string} cardNumber カード番号
 * @return {boolean}
 */
export function isValidCreditCard( cardNumber ) {
	const cleanNumber = cardNumber.replace( /\s/g, '' );

	if ( ! /^\d+$/.test( cleanNumber ) ) {
		return false;
	}

	let sum = 0;
	let isEven = false;

	for ( let i = cleanNumber.length - 1; i >= 0; i-- ) {
		let digit = parseInt( cleanNumber[ i ], 10 );

		if ( isEven ) {
			digit *= 2;
			if ( digit > 9 ) {
				digit -= 9;
			}
		}

		sum += digit;
		isEven = ! isEven;
	}

	return sum % 10 === 0;
}

export default {
	isValidEmail,
	isValidUrl,
	isValidPhoneJP,
	isValidZipJP,
	isNumeric,
	isInteger,
	isInRange,
	isValidLength,
	isNotEmpty,
	isValidDate,
	isValidHexColor,
	validatePasswordStrength,
	isValidCreditCard,
};
