package com.usky.system.controller.web;

import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import com.usky.common.core.bean.ApiResult;
import com.usky.common.core.constants.CacheConstants;
import com.usky.common.core.utils.StringUtils;
import com.usky.common.redis.core.RedisService;
import com.usky.system.controller.web.page.TableDataInfo;
import com.usky.system.domain.SysUserOnline;
import com.usky.system.model.LoginUser;
import com.usky.system.service.ISysUserOnlineService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.slf4j.Logger;

/**
 * 在线用户监控
 *
 */
@RestController
@RequestMapping("/online")
public class SysUserOnlineController {
    private final Logger logger = LoggerFactory.getLogger(SysUserOnlineController.class);

    @Autowired
    private ISysUserOnlineService userOnlineService;

    @Autowired
    private RedisService redisService;

    private TableDataInfo getDataTable(List<SysUserOnline> userOnlineList, int pageNum, int pageSize, long total) {
        TableDataInfo dataInfo = new TableDataInfo();
        dataInfo.setRows(userOnlineList);
        dataInfo.setTotal(total);
        dataInfo.setPageNum(pageNum);
        dataInfo.setPageSize(pageSize);
        dataInfo.setPages((int) Math.ceil((double) total / pageSize));
        return dataInfo;
    }

    @GetMapping("/list")
    public ApiResult<TableDataInfo> list(@RequestParam(required = false, defaultValue = "1") Integer page,
                                         @RequestParam(required = false, defaultValue = "10") Integer size,
                                         @RequestParam(required = false) String ipaddr,
                                         @RequestParam(required = false) String userName) {
        try {
            Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
            if (keys == null || keys.isEmpty()) {
                logger.error("Redis密钥为null或为空");
                return ApiResult.error("SYS-0000", "Redis密钥为null或为空");
            }
            Map<String, List<SysUserOnline>> userOnlineMap = new HashMap<>();

            for (String key : keys) {
                // 检查键是否存在并且未过期
                if (redisService.hasKey(key)) {
                    LoginUser user = redisService.getCacheObject(key);
                    if (user != null) {
                        if (ipaddr != null && !ipaddr.equals(user.getIpaddr())) {
                            continue;
                        }
                        if (userName != null && !userName.equals(user.getUsername())) {
                            continue;
                        }
                        SysUserOnline online = userOnlineService.loginUserToUserOnline(user);
                        if (online != null) {
                            List<SysUserOnline> list = userOnlineMap.computeIfAbsent(user.getUsername(), k -> new ArrayList<>());
                            list.add(online);
                        }
                    }
                }
            }

            List<SysUserOnline> userOnlineList = new ArrayList<>();
            for (Map.Entry<String, List<SysUserOnline>> entry : userOnlineMap.entrySet()) {
                List<SysUserOnline> sortedList = entry.getValue();
                sortedList.sort(Comparator.comparing(SysUserOnline::getLoginTime).reversed());
                if (!sortedList.isEmpty()) {
                    SysUserOnline lastOnline = sortedList.get(0);
                    lastOnline.setLoginCount(sortedList.size()); // 设置登录次数
                    userOnlineList.add(lastOnline);
                }
            }

            // 按照登录时间降序排序
            userOnlineList.sort(Comparator.comparing(SysUserOnline::getLoginTime).reversed());

            long total = userOnlineList.size();
            int start = (page - 1) * size;
            int end = Math.min(start + size, (int) total);
            List<SysUserOnline> pageList = userOnlineList.subList(start, end);

            return ApiResult.success(getDataTable(pageList, page, size, total));
        } catch (Exception ex) {
            logger.error("处理/online/list错误", ex);
            return ApiResult.error("SYS-0001", "内部系统错误", ex.getMessage());
        }
    }

    @GetMapping("/history")
    public ApiResult<TableDataInfo> listOtherLogins(@RequestParam Long userid,
                                                    @RequestParam(required = false, defaultValue = "1") Integer page,
                                                    @RequestParam(required = false, defaultValue = "10") Integer size) {
        try {
            Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
            if (keys == null || keys.isEmpty()) {
                logger.error("Redis密钥为null或为空");
                return ApiResult.error("SYS-0000", "Redis密钥为null或为空");
            }
            List<SysUserOnline> userOnlineList = new ArrayList<>();

            for (String key : keys) {
                if (redisService.hasKey(key)) {
                    LoginUser user = redisService.getCacheObject(key);
                    if (user != null && user.getUserid().equals(userid)) {
                        SysUserOnline online = userOnlineService.loginUserToUserOnline(user);
                        if (online != null) {
                            userOnlineList.add(online);
                        }
                    }
                }
            }

            // 按照登录时间降序排序
            userOnlineList.sort(Comparator.comparing(SysUserOnline::getLoginTime).reversed());
            // 排除最后一条记录，只保留其他记录
//            if (!userOnlineList.isEmpty()) {
//                userOnlineList = userOnlineList.subList(1, userOnlineList.size());
//            }

            long total = userOnlineList.size();
            int start = (page - 1) * size;
            int end = Math.min(start + size, (int) total);
            List<SysUserOnline> pageList = userOnlineList.subList(start, end);

            return ApiResult.success(getDataTable(pageList, page, size, total));
        } catch (Exception ex) {
            logger.error("处理/online/listOtherLogins错误", ex);
            return ApiResult.error("SYS-0001", "内部服务器错误", ex.getMessage());
        }
    }

    /**
     * 强退用户
     */
//    @RequiresPermissions("monitor:online:forceLogout")
    @DeleteMapping("/{tokenId}")
    public ApiResult forceLogout(@PathVariable String tokenId) {
        try {
            if (StringUtils.isBlank(tokenId)) {
                logger.error("强制注销时Token为空");
                return ApiResult.error("SYS-0004", "强制注销需要Token");
            }

            String key = CacheConstants.LOGIN_TOKEN_KEY + tokenId;
            boolean deleted = redisService.deleteObject(key);
            if (deleted) {
                logger.info("tokenId为 {} 的用户已被强制注销.", tokenId);
                return ApiResult.success();
            } else {
                logger.warn("未能找到并删除tokenId为 {} 的用户会话", tokenId);
                return ApiResult.error("SYS-0002", "未找到会话或已删除会话");
            }
        } catch (Exception ex) {
            logger.error("处理tokenId {} 的forceLogout时出错", tokenId, ex);
            return ApiResult.error("SYS-0003", "强制注销时出现内部系统错误", ex.getMessage());
        }
    }

    @DeleteMapping("/logoutMany/{userid}")
    public ApiResult forceLogoutMany(@PathVariable Long userid,
                                     @RequestParam(required = false, defaultValue = "1") Integer page,
                                     @RequestParam(required = false, defaultValue = "999") Integer size) {
        try {
            ApiResult<TableDataInfo> apiResult = listOtherLogins(userid, page, size);
            if (apiResult.isSuccess() && apiResult.getData() != null) {
                TableDataInfo tableDataInfo = apiResult.getData();
                List<SysUserOnline> userOnlineList = (List<SysUserOnline>) tableDataInfo.getRows();
                List<String> tokenIds = userOnlineList.stream()
                        .map(SysUserOnline::getTokenId)
                        .collect(Collectors.toList());

                // 执行强退操作
                for (String tokenId : tokenIds) {
                    String key = CacheConstants.LOGIN_TOKEN_KEY + tokenId;
                    boolean deleted = redisService.deleteObject(key);
                    if (deleted) {
                        logger.info("tokenId为 {} 的用户已被强制注销.", tokenId);
                    } else {
                        logger.warn("未能找到并删除tokenId为 {} 的用户会话", tokenId);
                    }
                }
                return ApiResult.success("已强制注销所有选中token.");
            } else {
                logger.error("调用 listOtherLogins 方法失败，原因：{}", apiResult.getMsg());
                return ApiResult.error("SYS-0003", "调用历史记录接口失败", apiResult.getMsg());
            }
        } catch (Exception ex) {
            logger.error("处理forceLogoutMany时出错", ex);
            return ApiResult.error("SYS-0003", "强制注销时出现内部系统错误", ex.getMessage());
        }
    }
}