package com.haha.admin.config;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;

@Configuration
public class JacksonConfig implements WebMvcConfigurer {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DATE_TIME_LENIENT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm[:ss]");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");

    /**
     * 关键：通过 WebMvcConfigurer 直接配置消息转换器
     * 确保自定义 ObjectMapper 被 Spring MVC 的 HTTP 响应序列化使用
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper());
        converters.add(0, converter); // 添加到最前面，优先使用
        System.out.println("[Jackson配置] 已通过 WebMvcConfigurer 注入自定义 ObjectMapper");
    }

    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();

        // 注册Long包装类转String序列化模块,避免前端精度丢失
        // 注意：不处理基本类型 long，因为分页字段（total/pageSize等）需要保持数字类型
        SimpleModule longModule = new SimpleModule("LongToStringModule");
        longModule.addSerializer(Long.class, ToStringSerializer.instance);
        mapper.registerModule(longModule);

        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class,
            new LocalDateTimeSerializer(DATE_TIME_FORMATTER));
        javaTimeModule.addDeserializer(LocalDateTime.class,
            new LenientLocalDateTimeDeserializer());

        javaTimeModule.addSerializer(LocalDate.class,
            new LocalDateSerializer(DATE_FORMATTER));
        javaTimeModule.addDeserializer(LocalDate.class,
            new LocalDateDeserializer(DATE_FORMATTER));

        javaTimeModule.addSerializer(LocalTime.class,
            new LocalTimeSerializer(TIME_FORMATTER));
        javaTimeModule.addDeserializer(LocalTime.class,
            new LocalTimeDeserializer(TIME_FORMATTER));

        mapper.registerModule(javaTimeModule);
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        System.out.println("[Jackson配置] ObjectMapper 初始化完成，Long -> String 序列化已启用");
        return mapper;
    }

    public static class LenientLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(com.fasterxml.jackson.core.JsonParser p,
                                        com.fasterxml.jackson.databind.DeserializationContext ctxt) throws IOException {
            String text = p.getValueAsString();
            if (text == null || text.isBlank()) {
                return null;
            }
            text = text.trim();
            
            // 1. 尝试解析 ISO 8601 格式: 2026-04-09T16:00:00.000Z
            try {
                ZonedDateTime zonedDateTime = ZonedDateTime.parse(text);
                return zonedDateTime.toLocalDateTime();
            } catch (DateTimeParseException e) {
                // 不是 ISO 8601 格式，继续尝试其他格式
            }
            
            // 2. 尝试解析标准格式: yyyy-MM-dd HH:mm:ss
            try {
                return LocalDateTime.parse(text, DATE_TIME_FORMATTER);
            } catch (Exception e) {
                // 继续尝试其他格式
            }
            
            // 3. 尝试解析缺少秒的格式: yyyy-MM-dd HH:mm
            try {
                String padded = text.length() == 16 ? text + ":00" : text;
                return LocalDateTime.parse(padded, DATE_TIME_FORMATTER);
            } catch (Exception ex) {
                throw new IOException(
                    "无法解析日期时间: " + text + ", 支持格式: yyyy-MM-dd HH:mm:ss 或 ISO 8601", ex);
            }
        }
    }
}
