package com.zt.plat.module.erp.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.*;
import java.util.stream.Collectors;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.erp.enums.ErrorCodeConstants.*;
import static dm.jdbc.util.DriverUtil.log;


/**
 * @author wuxz
 * @create 2022-06-07 20:54
 */
@Primary
@Configuration
public class MyRedisConfig {

    @Resource
    private RedisTemplate redisTemplate;

    @Bean(value = "MyRedisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // 通过 Jackson 组件进行序列化
        RedisSerializer<Object> serializer = redisSerializer();

        // key 和 value
        // 一般来说， redis-key采用字符串序列化；
        // redis-value采用json序列化， json的体积小，可读性高，不需要实现serializer接口。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }


    @Bean
    public RedisSerializer<Object> redisSerializer() {
        //创建JSON序列化器
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // objectMapper.enableDefaultTyping()被弃用
        objectMapper.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.WRAPPER_ARRAY);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }


    //list
    public Map<String, List<String>> numbers(JSONArray dataArray, String key, String dataKey) {
        // 使用 Redis 获取缓存数据
        Map<String, List<String>> numbers = new HashMap<>();
        List<String> cachedNumbers = (List<String>) redisTemplate.opsForValue().get(key);
        if (cachedNumbers == null) {
            cachedNumbers = new ArrayList<>();
        }

        // 提取有效的 BUKRS 编号
        List<String> existingNumbers;
        if (dataArray != null) {
            // 将dataKey按"-"分割成多个部分
            String[] keyParts = dataKey.split("-");
            existingNumbers = dataArray.stream()
                    .filter(Objects::nonNull)
                    .map(dataJson -> {
                        JSONObject jsonObject = (JSONObject) dataJson;
                        // 根据每个部分逐级获取值并拼接
                        StringBuilder sb = new StringBuilder();
                        for (String part : keyParts) {
                            String value = jsonObject.getString(part);
                            if (value != null) {
                                if (sb.length() > 0) {
                                    sb.append("-");
                                }
                                sb.append(value.trim());
                            } else {
                                // 如果某一部分为空，则整个值视为无效
                                return null;
                            }
                        }
                        return sb.toString();
                    })
                    .filter(Objects::nonNull) // 过滤掉无效值
                    .collect(Collectors.toList());
        } else {
            existingNumbers = new ArrayList<>();
        }

        // 找出共同存在的编号
        Set<String> cachedNumberSet = new HashSet<>(cachedNumbers != null ? cachedNumbers : new ArrayList<>());
        List<String> commonNumbers = existingNumbers.stream()
                .filter(cachedNumberSet::contains)
                .collect(Collectors.toList());
        numbers.put("com", commonNumbers);

        //找出需要删除的字段。只有erp查询全部的接口能用到
        List<String> deleteNumbers = cachedNumberSet.stream()
                .filter(num -> !existingNumbers.contains(num))
                .collect(Collectors.toList());
        numbers.put("delete", deleteNumbers);

        // 找出需要新增的编号
        List<String> newNumbers = existingNumbers.stream()
                .filter(num -> !cachedNumberSet.contains(num))
                .toList();

        // 合并所有编号
        List<String> allNumbers = new ArrayList<>(cachedNumbers);
        allNumbers.addAll(newNumbers);
        numbers.put("all", allNumbers);

        return numbers;
    }

    public void updateRedisCache(String key, List<String> allnumbers) {
        // 使用 Redis 更新缓存数据
        redisTemplate.opsForValue().set(key, allnumbers);
    }

    public List<String> getRedisCache(String key) {
        // 使用 Redis 更新缓存数据
        return (List<String>) redisTemplate.opsForValue().get(key);
    }

    //map
    public Map<String, Long> getRedisCacheMap(String key) {
        try {
            // 使用 Redis 获取缓存数据
            Map<String, Long> result = (Map<String, Long>) redisTemplate.opsForHash().entries(key);
            return result;
        } catch (Exception e) {
            throw exception(ERP_REDIS_EXISTS);
        }
    }

    public void addRedisCacheMap(String key, Map<String, Long> allnumbers) {
        // 使用 Redis 更新缓存数据
        redisTemplate.opsForHash().putAll(key, allnumbers);
    }

    public void deleteRedisCacheMap(String key, List<String> deleteNumbers) {
        if (deleteNumbers == null || deleteNumbers.isEmpty()) {
            log.debug("No items to delete from Redis hash: {}", key);
            return;
        }

        try {
            Object[] keysToDelete = deleteNumbers.toArray(new String[0]);
            Long deletedCount = redisTemplate.opsForHash().delete(key, keysToDelete);
            log.debug("Deleted" + deletedCount + "items from Redis hash:" + key);
        } catch (Exception e) {
            log.error("Failed to delete items from Redis hash:" + key, e);
            throw e;
        }
    }


}