package cn.meowrain.aioj.backend.framework.log.event;

import cn.hutool.core.util.StrUtil;
import cn.meowrain.aioj.backend.framework.core.jackson.JavaTimeModule;
import cn.meowrain.aioj.backend.framework.log.config.AIOJLogPropertiesConfiguration;
import cn.meowrain.aioj.backend.upms.api.entity.SysLog;
import cn.meowrain.aioj.backend.upms.api.feign.RemoteLogService;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;

import java.util.Objects;

@RequiredArgsConstructor
public class SysLogListener implements InitializingBean {

	private final static ObjectMapper objectMapper = new ObjectMapper();

	private final RemoteLogService remoteLogService;

	private final AIOJLogPropertiesConfiguration logProperties;

	@SneakyThrows
	@Async
	@Order
	@EventListener(SysLogEvent.class)
	public void saveLog(SysLogEvent sysLogEvent) {
		SysLogEventSource source = (SysLogEventSource) sysLogEvent.getSource();
		SysLog sysLog = new SysLog();
		BeanUtils.copyProperties(source, sysLog);

		// json 格式刷参数放在异步中处理，提升性能
		if (Objects.nonNull(source.getBody())) {
			String params = objectMapper.writeValueAsString(source.getBody());
			sysLog.setParams(StrUtil.subPre(params, logProperties.getMaxLength()));
		}

		remoteLogService.saveLog(sysLog);
	}

	/**
	 * 在 Bean 初始化后执行，用于初始化 ObjectMapper
	 * @throws Exception
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		// 给 ObjectMapper 添加 MixIn（用于过滤字段）
		objectMapper.addMixIn(Object.class, PropertyFilterMixIn.class);
		String[] ignorableFieldNames = logProperties.getExcludeFields().toArray(new String[0]);

		FilterProvider filters = new SimpleFilterProvider().addFilter("filter properties by name",
				SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
		objectMapper.setFilterProvider(filters);
		objectMapper.registerModule(new JavaTimeModule());
	}

	/**
	 * 属性过滤混合类：用于通过名称过滤属性
	 *
	 * @author lengleng
	 * @date 2025/05/31
	 */
	@JsonFilter("filter properties by name")
	class PropertyFilterMixIn {

	}

}
