/**
 * Formatting Utilities
 * フォーマット関数
 */

/**
 * 数値を通貨形式にフォーマット
 * @param {number} value    数値
 * @param {string} currency 通貨コード
 * @param {string} locale   ロケール
 * @return {string}
 */
export function formatCurrency( value, currency = 'JPY', locale = 'ja-JP' ) {
	return new Intl.NumberFormat( locale, {
		style: 'currency',
		currency,
	} ).format( value );
}

/**
 * 数値をカンマ区切りにフォーマット
 * @param {number} value 数値
 * @return {string}
 */
export function formatNumber( value ) {
	return new Intl.NumberFormat( 'ja-JP' ).format( value );
}

/**
 * 日付をフォーマット
 * @param {Date|string} date   日付
 * @param {string}      format フォーマット
 * @return {string}
 */
export function formatDate( date, format = 'YYYY-MM-DD' ) {
	const d = new Date( date );

	if ( isNaN( d.getTime() ) ) {
		return '';
	}

	const year = d.getFullYear();
	const month = String( d.getMonth() + 1 ).padStart( 2, '0' );
	const day = String( d.getDate() ).padStart( 2, '0' );
	const hours = String( d.getHours() ).padStart( 2, '0' );
	const minutes = String( d.getMinutes() ).padStart( 2, '0' );
	const seconds = String( d.getSeconds() ).padStart( 2, '0' );

	return format
		.replace( 'YYYY', year )
		.replace( 'MM', month )
		.replace( 'DD', day )
		.replace( 'HH', hours )
		.replace( 'mm', minutes )
		.replace( 'ss', seconds );
}

/**
 * 相対時間をフォーマット（○分前、○日前など）
 * @param {Date|string} date 日付
 * @return {string}
 */
export function formatRelativeTime( date ) {
	const now = new Date();
	const past = new Date( date );
	const diffInSeconds = Math.floor( ( now - past ) / 1000 );

	if ( diffInSeconds < 60 ) {
		return `${ diffInSeconds }秒前`;
	}

	const diffInMinutes = Math.floor( diffInSeconds / 60 );
	if ( diffInMinutes < 60 ) {
		return `${ diffInMinutes }分前`;
	}

	const diffInHours = Math.floor( diffInMinutes / 60 );
	if ( diffInHours < 24 ) {
		return `${ diffInHours }時間前`;
	}

	const diffInDays = Math.floor( diffInHours / 24 );
	if ( diffInDays < 30 ) {
		return `${ diffInDays }日前`;
	}

	const diffInMonths = Math.floor( diffInDays / 30 );
	if ( diffInMonths < 12 ) {
		return `${ diffInMonths }ヶ月前`;
	}

	const diffInYears = Math.floor( diffInMonths / 12 );
	return `${ diffInYears }年前`;
}

/**
 * ファイルサイズをフォーマット
 * @param {number} bytes    バイト数
 * @param {number} decimals 小数点以下の桁数
 * @return {string}
 */
export function formatFileSize( bytes, decimals = 2 ) {
	if ( bytes === 0 ) {
		return '0 Bytes';
	}

	const k = 1024;
	const dm = decimals < 0 ? 0 : decimals;
	const sizes = [ 'Bytes', 'KB', 'MB', 'GB', 'TB' ];

	const i = Math.floor( Math.log( bytes ) / Math.log( k ) );

	return (
		parseFloat( ( bytes / Math.pow( k, i ) ).toFixed( dm ) ) +
		' ' +
		sizes[ i ]
	);
}

/**
 * 電話番号をフォーマット
 * @param {string} phone 電話番号
 * @return {string}
 */
export function formatPhoneNumber( phone ) {
	const cleaned = phone.replace( /\D/g, '' );

	// 携帯電話（090/080/070）
	if ( cleaned.match( /^(090|080|070)/ ) ) {
		return cleaned.replace( /(\d{3})(\d{4})(\d{4})/, '$1-$2-$3' );
	}

	// 固定電話（東京03など）
	if ( cleaned.match( /^0\d{9}$/ ) ) {
		return cleaned.replace( /(\d{2})(\d{4})(\d{4})/, '$1-$2-$3' );
	}

	// その他
	return cleaned.replace( /(\d{3})(\d{3})(\d{4})/, '$1-$2-$3' );
}

/**
 * 郵便番号をフォーマット
 * @param {string} zip 郵便番号
 * @return {string}
 */
export function formatZipCode( zip ) {
	const cleaned = zip.replace( /\D/g, '' );
	if ( cleaned.length === 7 ) {
		return cleaned.replace( /(\d{3})(\d{4})/, '$1-$2' );
	}
	return zip;
}

/**
 * 文字列を省略
 * @param {string} str       文字列
 * @param {number} maxLength 最大長
 * @param {string} suffix    省略記号
 * @return {string}
 */
export function truncateString( str, maxLength = 100, suffix = '...' ) {
	if ( str.length <= maxLength ) {
		return str;
	}
	return str.substring( 0, maxLength - suffix.length ) + suffix;
}

/**
 * ケバブケースに変換
 * @param {string} str 文字列
 * @return {string}
 */
export function toKebabCase( str ) {
	return str
		.replace( /([a-z])([A-Z])/g, '$1-$2' )
		.replace( /[\s_]+/g, '-' )
		.toLowerCase();
}

/**
 * キャメルケースに変換
 * @param {string} str 文字列
 * @return {string}
 */
export function toCamelCase( str ) {
	return str
		.toLowerCase()
		.replace( /[-_\s](.)/g, ( _, char ) => char.toUpperCase() );
}

/**
 * スネークケースに変換
 * @param {string} str 文字列
 * @return {string}
 */
export function toSnakeCase( str ) {
	return str
		.replace( /([a-z])([A-Z])/g, '$1_$2' )
		.replace( /[\s-]+/g, '_' )
		.toLowerCase();
}

/**
 * タイトルケースに変換
 * @param {string} str 文字列
 * @return {string}
 */
export function toTitleCase( str ) {
	return str
		.toLowerCase()
		.split( ' ' )
		.map( ( word ) => word.charAt( 0 ).toUpperCase() + word.slice( 1 ) )
		.join( ' ' );
}

/**
 * URLスラッグに変換
 * @param {string} str 文字列
 * @return {string}
 */
export function toSlug( str ) {
	return str
		.toLowerCase()
		.trim()
		.replace( /[^\w\s-]/g, '' )
		.replace( /[\s_-]+/g, '-' )
		.replace( /^-+|-+$/g, '' );
}

export default {
	formatCurrency,
	formatNumber,
	formatDate,
	formatRelativeTime,
	formatFileSize,
	formatPhoneNumber,
	formatZipCode,
	truncateString,
	toKebabCase,
	toCamelCase,
	toSnakeCase,
	toTitleCase,
	toSlug,
};
