package com.takensoft.common.config;

import jakarta.validation.constraints.NotNull;
import net.rakugakibox.util.YamlResourceBundle;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * @author  : takensoft
 * @since   : 2025.01.22
 * @modification
 *     since    |    author    | description
 *  2025.01.22  |  takensoft   | 최초 등록
 *
 * Spring의 다국어 메시지 처리를 위한 설정 Config
 */
@Configuration
public class MessageConfig {

    /**
     * ResourceBundleMessageSource를 확장하여 YAML 형식의 메시지를 지원하는 내부 정적 클래스
     */
    private static class YamlMessageSource extends ResourceBundleMessageSource {
        /**
         * @param basename - 메시지 번들의 기본 이름
         * @param locale - 로케일 정보
         * @return 해당 로케일의 ResourceBundle 객체
         * @throws MissingResourceException - 해당 리소스를 찾지 못할 경우 예외 발생
         *
         * YAML 형식의 메시지 번들 호출
         */
        @NotNull
        @Override
        protected ResourceBundle doGetBundle(@NotNull String basename, @NotNull Locale locale) throws MissingResourceException {
            return ResourceBundle.getBundle(basename, locale, YamlResourceBundle.Control.INSTANCE);
        }
    }

    /**
     * @return MessageSource 객체
     *
     * YAML 메시지 소스를 설정
     */
    @Bean
    public MessageSource messageSource() {
        YamlMessageSource messageSource = new YamlMessageSource();
                          messageSource.setBasename("message/messages");    // 메시지 찾을 위치
                          messageSource.setDefaultEncoding("UTF-8");        // 인코딩
                          messageSource.setAlwaysUseMessageFormat(true);    // 메시지 포멧 규칙
                          messageSource.setUseCodeAsDefaultMessage(true);   // 메시지를 못찾으면 그 자체를 디폴트 메시지로 사용
                          messageSource.setFallbackToSystemLocale(true);    // 특정 로케일에 대한 파일을 발견하지 못 할 경우, 시스템 로케일로 폴백
        return messageSource;
    }
}
