package com.ruoyi.framework.web.service;

import java.nio.charset.StandardCharsets;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.filter.Filter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;

/**
 * 登录用户 Redis 存储：使用 Jackson 原始 JSON 字节，避免 FastJSON2 反序列化 LoginUser 嵌套对象异常。
 */
@Component
public class LoginUserRedisStore
{
    private static final Logger log = LoggerFactory.getLogger(LoginUserRedisStore.class);

    private static final Filter LEGACY_AUTO_TYPE_FILTER =
            JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);

    private final RedisTemplate<Object, Object> redisTemplate;

    private final ObjectMapper objectMapper;

    public LoginUserRedisStore(RedisTemplate<Object, Object> redisTemplate)
    {
        this.redisTemplate = redisTemplate;
        this.objectMapper = new ObjectMapper();
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    public void save(String key, LoginUser loginUser, long timeoutMinutes)
    {
        if (StringUtils.isEmpty(key) || loginUser == null)
        {
            return;
        }
        try
        {
            byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
            byte[] valueBytes = objectMapper.writeValueAsBytes(loginUser);
            long seconds = Math.max(timeoutMinutes * 60L, 1L);
            redisTemplate.execute((RedisCallback<Void>) connection -> {
                connection.setEx(keyBytes, seconds, valueBytes);
                return null;
            });
        }
        catch (Exception e)
        {
            throw new IllegalStateException("登录缓存写入失败", e);
        }
    }

    public LoginUser load(String key)
    {
        if (StringUtils.isEmpty(key))
        {
            return null;
        }
        byte[] valueBytes = readRawBytes(key);
        if (valueBytes == null || valueBytes.length == 0)
        {
            return null;
        }
        LoginUser loginUser = readJackson(valueBytes);
        if (loginUser != null)
        {
            return loginUser;
        }
        loginUser = readLegacyFastJson(valueBytes);
        if (loginUser != null)
        {
            log.info("已兼容读取 FastJSON 格式登录缓存，key={}", key);
            return loginUser;
        }
        log.warn("登录缓存损坏，已删除 key={}", key);
        delete(key);
        return null;
    }

    public void delete(String key)
    {
        if (StringUtils.isNotEmpty(key))
        {
            redisTemplate.delete(key);
        }
    }

    private byte[] readRawBytes(String key)
    {
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        return redisTemplate.execute((RedisCallback<byte[]>) connection -> connection.get(keyBytes));
    }

    private LoginUser readJackson(byte[] bytes)
    {
        try
        {
            return objectMapper.readValue(bytes, LoginUser.class);
        }
        catch (Exception ignored)
        {
            return null;
        }
    }

    private LoginUser readLegacyFastJson(byte[] bytes)
    {
        try
        {
            String str = new String(bytes, StandardCharsets.UTF_8).trim();
            if (str.startsWith("\"") && str.endsWith("\""))
            {
                str = objectMapper.readValue(str, String.class);
            }
            return JSON.parseObject(str, LoginUser.class, LEGACY_AUTO_TYPE_FILTER);
        }
        catch (Exception ignored)
        {
            return null;
        }
    }
}
