package com.interplug.qcast.config.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.interplug.qcast.config.json.HtmlCharacterEscapes;
import io.micrometer.common.lang.NonNullApi;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Locale;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

/**
 * <pre>
 * Web Config
 * </pre>
 *
 * @author jaeyoung_lee (kkang090@gmail.com)
 */
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

	private final ObjectMapper objectMapper;

	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**").allowedOriginPatterns("*").allowCredentials(true).exposedHeaders("Authorization")
				.allowedMethods("GET", "PUT", "POST", "PATCH", "DELETE", "OPTIONS");
	}

	/**
	 * <pre>
	 * XSS(Cross Site Scripting) converter
	 * </pre>
	 * 
	 * @author KimYoungHyun (youngh.kim@kt.com)
	 * @return
	 */
	@Bean
	public MappingJackson2HttpMessageConverter jsonEscapeConverter() {
		ObjectMapper copy = objectMapper.copy();
		copy.getFactory().setCharacterEscapes(new HtmlCharacterEscapes());
		return new MappingJackson2HttpMessageConverter(copy);
	}

	/**
	 * 기본 로케일 설정
	 * @return LocaleResolver
	 */
	@Bean
	public LocaleResolver localeResolver() {
		HeaderLocaleResolver localeResolver = new HeaderLocaleResolver();
		localeResolver.setDefaultLocale(Locale.KOREA);
		return localeResolver;
	}

	/**
	 * 로케일 변경 인터셉터
	 * @return LocaleChangeInterceptor
	 */
	@Bean
	public LocaleChangeInterceptor localeChangeInterceptor() {
		LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
		localeChangeInterceptor.setParamName("lang");
		return localeChangeInterceptor;
	}

	/**
	 * 인터셉터 등록
	 * @param registry InterceptorRegistry
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(localeChangeInterceptor());
	}

	/**
	 * locale 변경을 위한 HeaderLocaleResolver
	 */
	@NonNullApi
	private static class HeaderLocaleResolver extends AcceptHeaderLocaleResolver {
		@Override
		public Locale resolveLocale(HttpServletRequest request) {
			String lang = request.getHeader("lang");
			if (lang == null || lang.isEmpty()) {
				return super.resolveLocale(request);
			}
			return new Locale(lang);
		}
	}
}
