package net.northking.cctp.common.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import net.northking.cctp.common.exception.ErrorEnum;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.common.log.HttpLogProducer;
import net.northking.cctp.common.log.HttpLogRabbitMQProducer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.client.RestTemplate;

/**
 * CCTP全局通用配置
 *
 * @author xiusong.xie
 * @since 1.0
 */
@Configuration
public class GlobalConfiguration
{
  private static final Logger logger = LoggerFactory.getLogger(GlobalConfiguration.class);

  @Bean
  @Primary
  @ConditionalOnMissingBean(ObjectMapper.class)
  public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
  {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
    // 找不到匹配属性时忽略报错
    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    // 不包含任何属性的bean也不报错
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    logger.info("注册公共组件提示：统一配置 JSON序列化忽略空值（包含NULL和空字符串）。");
    // 检查服务编码格式，如果不是utf-8，不能启动
    String encoding = System.getProperty("file.encoding");
    if (!"UTF-8".equals(encoding)) {
      logger.error("检查服务编码格式，如果不是UTF-8，不能启动，请使用-Dfile.encoding=UTF-8，指定编码格式启动程序");
      throw new PlatformRuntimeException(ErrorEnum.APPLICATION_ENCODING_ERROR);
    }
    return objectMapper;
  }


  /**
   * 注册密码加密类
   *
   * @return 密码加密类
   */
  @Bean
  @ConditionalOnMissingBean
  public PasswordEncoder passwordEncoder()
  {
    logger.info("注册公共组件提示：统一配置 使用 BCryptPasswordEncoder 加密密码。");
    return new BCryptPasswordEncoder();
  }

  /**
   * RestTemplate
   *
   * @return RestTemplate
   */
  @Bean
  @ConditionalOnMissingBean
  public RestTemplate restTemplate()
  {
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setConnectTimeout(5000);
    factory.setReadTimeout(5000);
    RestTemplate restTemplate = new RestTemplate(factory);
    logger.info("注册公共组件提示：统一配置 RestTemplate, 超时时间设置为5秒。");
    return restTemplate;
  }

  /**
   * RabbitMQ Config
   *
   * @param connectionFactory 消息队列链接工厂
   * @return RabbitListenerContainerFactory
   */
  @Bean
  public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory)
  {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setMessageConverter(new Jackson2JsonMessageConverter());
    logger.info("注册公共组件提示：统一配置 RabbitListenerContainerFactory, 使用Jackson转换消息内容。");
    return factory;
  }


  @Bean
  @ConditionalOnMissingBean
  public HttpLogProducer httpLogProducer(RabbitTemplate rabbitTemplate, ObjectMapper objectMapper)
  {
    return new HttpLogRabbitMQProducer(rabbitTemplate, objectMapper);
  }
}
