package org.example.Api;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.example.Entity.System.LoginUserInfo;
import org.example.Utils.CacheUtil;
import org.example.Utils.WebConfigUtil_web;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import static org.example.Utils.NativeExtensionUtils.toBoolean;

@Component
public class SingleUserHandler {

    // 登录状态枚举
    public enum UserLoginState {
        LOGIN(1), UNLOGIN(2), WAIT_LOGIN_OUT(3);

        private final int value;

        UserLoginState(int value) {
            this.value = value;
        }
    }

    // 关键修改：缓存存储 全局 LoginUserInfo + 状态 + SessionId（用Map封装）
    private static class CacheUserInfo implements Serializable {
        private static final long serialVersionUID = 1L;
        private LoginUserInfo loginUserInfo; // 全局用户信息（🔥 改动：替换内部类，使用全局LoginUserInfo）
        private UserLoginState state;
        private String sessionId;

        // 无参构造 + getter/setter（支持Jackson序列化）
        public CacheUserInfo() {
        }

        public CacheUserInfo(LoginUserInfo loginUserInfo, UserLoginState state, String sessionId) {
            this.loginUserInfo = loginUserInfo;
            this.state = state;
            this.sessionId = sessionId;
        }

        // getter 方法（🔥 改动：补全序列化必需的getter，否则Jackson无法读取字段）
        public LoginUserInfo getLoginUserInfo() {
            return loginUserInfo;
        }

        public UserLoginState getState() {
            return state;
        }

        public String getSessionId() {
            return sessionId;
        }

        // 🔥 改动：补全setter，用于修改状态和SessionId
        public void setState(UserLoginState state) {
            this.state = state;
        }

        public void setSessionId(String sessionId) {
            this.sessionId = sessionId;
        }
    }

    private static boolean getUseSingleUser() {
        // 每次调用都会重新执行 WebConfigUtil_web.get，拿到最新值
        return toBoolean(WebConfigUtil_web.get("SingleUser", ""));
    }

    public static String cacheKey = "loginDict";


    private static RedisTemplate<String, Object> redisTemplate; // 用Redis替代原C#的CacheUtil

    private static final ReentrantLock lock = new ReentrantLock(); // 替代lock语句

    // 获取登录用户字典
    // 获取登录用户字典
    @SuppressWarnings("unchecked")
    private static Map<String, CacheUserInfo> getInfoDict() {
        Object obj = CacheUtil.get(cacheKey);
        if (obj == null || !(obj instanceof Map)) {
            return new HashMap<>();
        }

//        Map<String, Object> rawMap = (Map<String, Object>) obj;
//        Map<String, CacheUserInfo> resultMap = new HashMap<>();
//
//        // 🔥 关键修改：不用 new ObjectMapper()，用 CacheUtil 里配置好的 OBJECT_MAPPER
//        ObjectMapper mapper = CacheUtil.OBJECT_MAPPER;
//
//        for (Map.Entry<String, Object> entry : rawMap.entrySet()) {
//            String sessionId = entry.getKey();
//            Object value = entry.getValue();
//            if (value instanceof LinkedHashMap) {
//                // 现在用的是带“忽略大小写”配置的 mapper，能识别 userId -> UserId
//                CacheUserInfo cacheUserInfo = mapper.convertValue(value, CacheUserInfo.class);
//                resultMap.put(sessionId, cacheUserInfo);
//            }
//        }
//
//        System.out.println("【getInfoDict】转换后的缓存大小：" + resultMap.size());
        return (Map<String, CacheUserInfo>) obj;
    }

    // 添加登录用户（新登录会踢掉旧登录）
    // 🔥 改回：参数恢复为String username（适配其他地方的调用，传的是从实例里拿的UserId/UserName）
    public static void add(String sessionId, String username) {
        // 🔥 改回：恢复原有参数校验（去掉luser非空校验）
        if (StringUtils.isEmpty(sessionId) || StringUtils.isEmpty(username) || !getUseSingleUser()) return;

        lock.lock();
        try {
            Map<String, CacheUserInfo> dict = getInfoDict();
            // 🔥 逻辑不变：按username（实际是UserId）查询（统一标识字段）
            CacheUserInfo cacheUserInfo = getLoginUser(username);

            if (cacheUserInfo == null) {
                // 🔥 适配：创建全局LoginUserInfo实例，设置UserId为username（其他字段保持默认）
                LoginUserInfo loginUserInfo = new LoginUserInfo();
                loginUserInfo.UserId = username; // 核心：把传入的username（UserId）赋值给全局用户实例
                // 实例化CacheUserInfo，封装全局LoginUserInfo+状态+SessionId
                cacheUserInfo = new CacheUserInfo(loginUserInfo, UserLoginState.LOGIN, sessionId);
            } else {
                dict.remove(cacheUserInfo.getSessionId()); // 移除旧会话
                cacheUserInfo.setState(UserLoginState.LOGIN); // 更新状态
                cacheUserInfo.setSessionId(sessionId); // 更新SessionId

            }
            dict.put(sessionId, cacheUserInfo);
            // 缓存2小时
//            redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
            CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
        } finally {
            lock.unlock();
        }
    }

    // 移除会话
    public static void remove(String sessionId) {
        if (StringUtils.isEmpty(sessionId) || !getUseSingleUser()) return;

        lock.lock();
        try {
            Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动：适配CacheUserInfo类型
            dict.remove(sessionId);
//            redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
            CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
        } finally {
            lock.unlock();
        }
    }

    // 标记用户为未登录状态
    public static void unLogin(String sessionId) {
        if (StringUtils.isEmpty(sessionId) || !getUseSingleUser()) return;

        lock.lock();
        try {
            Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动：适配CacheUserInfo类型
            if (dict.containsKey(sessionId)) {
                dict.get(sessionId).setState(UserLoginState.UNLOGIN); // 🔥 改动：用setter修改状态
//                redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
                CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
            }
        } finally {
            lock.unlock();
        }
    }

    // 标记用户为等待登出状态
    public static void waitLoginOut(String sessionId) {
        if (StringUtils.isEmpty(sessionId) || !getUseSingleUser()) return;

        lock.lock();
        try {
            Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动：适配CacheUserInfo类型
            if (dict.containsKey(sessionId)) {
                dict.get(sessionId).setState(UserLoginState.WAIT_LOGIN_OUT); // 🔥 改动：用setter修改状态
//                redisTemplate.opsForValue().set(cacheKey, dict, 2, TimeUnit.HOURS);
                CacheUtil.set(cacheKey, dict, Duration.ofDays(2), null);
            }
        } finally {
            lock.unlock();
        }
    }

    // 根据用户名查询登录信息
    // 🔥 改动：参数保持String userId（实际传入的是username=UserId），按UserId查询
    private static CacheUserInfo getLoginUser(String userId) {
        if (StringUtils.isEmpty(userId) || !getUseSingleUser()) return null;

        lock.lock();
        try {
            Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动：适配CacheUserInfo类型
            for (CacheUserInfo info : dict.values()) {
                // 🔥 改动：按全局LoginUserInfo的UserId匹配（传入的username就是UserId）
                if (userId.equals(info.getLoginUserInfo().getUserId())) {
                    return info;
                }
            }
            return null;
        } finally {
            lock.unlock();
        }
    }

    // 检查用户是否已登录
    // 🔥 改动：参数保持String userId（适配外部调用，传的是UserId）
    public static boolean hasLoginUser(String userId) {
        if (!getUseSingleUser()) return false;
        CacheUserInfo info = getLoginUser(userId); // 🔥 改动：适配新的getLoginUser返回值
        return info != null && info.getState() == UserLoginState.LOGIN; // 🔥 改动：用getter获取状态
    }

    // 检查会话是否存在
    public static boolean hasSessionUser(String sessionId) {
        if (!getUseSingleUser()) return false;
        Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动：适配CacheUserInfo类型
        return dict.containsKey(sessionId);
    }

    /**
     * 检查指定会话是否处于未登录状态
     *
     * @param sessionId 会话ID
     * @return 若启用单用户登录且会话存在且状态为未登录，返回true；否则返回false
     */
    public static boolean hasUnLoginUser(String sessionId) {
        if (getUseSingleUser()) {
            Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动：适配CacheUserInfo类型
            if (dict != null && dict.containsKey(sessionId)) {
                // 注意：需确保LoginUserInfo中存在对应的状态枚举（此处假设已定义）
                return dict.get(sessionId).getState() == UserLoginState.UNLOGIN; // 🔥 改动：用getter获取状态
            }
        }
        return false;
    }

    /**
     * 检查指定会话是否处于等待登出状态
     *
     * @param sessionId 会话ID
     * @return 若启用单用户登录且会话存在且状态为等待登出，返回true；否则返回false
     */
    public static boolean hasWaitUnLoginUser(String sessionId) {
        if (getUseSingleUser()) {
            Map<String, CacheUserInfo> dict = getInfoDict(); // 🔥 改动：适配CacheUserInfo类型
            if (dict != null && dict.containsKey(sessionId)) {
                return dict.get(sessionId).getState() == UserLoginState.WAIT_LOGIN_OUT; // 🔥 改动：用getter获取状态
            }
        }
        return false;
    }
}