package com.qqchen.deploy.backend.system.service.impl;

import com.qqchen.deploy.backend.framework.utils.RedisUtil;
import com.qqchen.deploy.backend.framework.security.util.JwtTokenUtil;
import com.qqchen.deploy.backend.system.entity.User;
import com.qqchen.deploy.backend.system.model.query.OnlineUserQuery;
import com.qqchen.deploy.backend.system.model.vo.OnlineStatisticsVO;
import com.qqchen.deploy.backend.system.model.vo.OnlineUserVO;
import com.qqchen.deploy.backend.system.repository.IUserRepository;
import com.qqchen.deploy.backend.system.service.IOnlineUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 在线用户服务实现
 * 
 * @author qqchen
 * @date 2025-11-20
 */
@Slf4j
@Service
public class OnlineUserServiceImpl implements IOnlineUserService {
    
    @Resource
    private RedisUtil redisUtil;
    
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    
    @Resource
    private IUserRepository userRepository;
    
    // Redis Key前缀（使用JwtTokenUtil的统一Key）
    private static final String TOKEN_PREFIX = "auth:token:";
    private static final String PEAK_KEY = "online:peak:today";
    
    @Override
    public Page<OnlineUserVO> getOnlineUsers(OnlineUserQuery query) {
        List<OnlineUserVO> allOnlineUsers = getAllOnlineUsers();
        
        // 关键词过滤
        String keyword = query.getKeyword();
        if (keyword != null && !keyword.trim().isEmpty()) {
            String lowerKeyword = keyword.toLowerCase();
            allOnlineUsers = allOnlineUsers.stream()
                .filter(user -> 
                    user.getUsername().toLowerCase().contains(lowerKeyword) ||
                    (user.getNickname() != null && user.getNickname().toLowerCase().contains(lowerKeyword))
                )
                .collect(Collectors.toList());
        }
        
        // 排序：按登录时间倒序
        allOnlineUsers.sort(Comparator.comparing(OnlineUserVO::getLoginTime).reversed());
        
        // 分页（使用BaseQuery的pageNum从1开始）
        int pageNum = query.getPageNum() != null ? query.getPageNum() : 1;
        int pageSize = query.getPageSize() != null ? query.getPageSize() : 10;
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, allOnlineUsers.size());
        List<OnlineUserVO> pageContent = start < allOnlineUsers.size() ? allOnlineUsers.subList(start, end) : Collections.emptyList();
        
        // 创建PageRequest（注意：Spring Data的page从0开始）
        PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize);
        return new PageImpl<>(pageContent, pageRequest, allOnlineUsers.size());
    }
    
    @Override
    public List<OnlineUserVO> getAllOnlineUsers() {
        // 获取所有Token Key
        Set<String> keys = redisUtil.keys(TOKEN_PREFIX + "*");
        if (keys == null || keys.isEmpty()) {
            return Collections.emptyList();
        }
        
        List<OnlineUserVO> onlineUsers = new ArrayList<>();
        
        for (String key : keys) {
            try {
                // 从Tok Key中提取userId
                String userIdStr = key.replace(TOKEN_PREFIX, "");
                Long userId = Long.parseLong(userIdStr);
                
                // 获取Token信息（包含在线状态）
                Map<String, Object> tokenInfo = jwtTokenUtil.getTokenInfo(userId);
                if (tokenInfo == null) continue;
                
                String loginTimeStr = (String) tokenInfo.get("loginTime");
                String ipAddress = (String) tokenInfo.get("ipAddress");
                String browser = (String) tokenInfo.get("browser");
                String os = (String) tokenInfo.get("os");
                
                // 查询用户详细信息
                User user = userRepository.findById(userId).orElse(null);
                if (user == null) continue;
                
                // 解析时间
                LocalDateTime loginTime = loginTimeStr != null ? LocalDateTime.parse(loginTimeStr) : LocalDateTime.now();
                
                // 计算在线时长
                long onlineDuration = Duration.between(loginTime, LocalDateTime.now()).getSeconds();
                
                OnlineUserVO vo = OnlineUserVO.builder()
                    .userId(userId)
                    .username(user.getUsername())
                    .nickname(user.getNickname())
                    .departmentName(user.getDepartment() != null ? user.getDepartment().getName() : null)
                    .loginTime(loginTime)
                    .lastActiveTime(loginTime)  // 由于没有心跳，最后活跃时间=登录时间
                    .onlineDuration(onlineDuration)
                    .ipAddress(ipAddress)
                    .browser(browser)
                    .os(os)
                    .build();
                
                onlineUsers.add(vo);
            } catch (Exception e) {
                log.error("解析在线用户信息失败: key={}", key, e);
            }
        }
        
        return onlineUsers;
    }
    
    @Override
    public OnlineStatisticsVO getStatistics() {
        int totalOnline = getAllOnlineUsers().size();
        
        // 获取今日峰值
        Integer todayPeak = totalOnline;
        Object peakObj = redisUtil.get(PEAK_KEY);
        if (peakObj != null) {
            todayPeak = Math.max(totalOnline, getIntValue(peakObj));
        }
        
        // 计算平均在线时长
        String averageOnlineTime = calculateAverageOnlineTime();
        
        return OnlineStatisticsVO.builder()
            .totalOnline(totalOnline)
            .todayPeak(todayPeak)
            .averageOnlineTime(averageOnlineTime)
            .build();
    }
    
    @Override
    public void kickUser(Long userId) {
        // 删除Token（同时删除了在线信息）
        jwtTokenUtil.removeToken(userId);
        log.warn("用户已被强制下线: userId={}", userId);
    }
    
    /**
     * 更新今日峰值
     */
    private void updateTodayPeak() {
        int currentOnline = getAllOnlineUsers().size();
        Object peakObj = redisUtil.get(PEAK_KEY);
        int currentPeak = peakObj != null ? getIntValue(peakObj) : 0;
        
        if (currentOnline > currentPeak) {
            // 更新峰值，保留到今天结束
            long secondsUntilMidnight = Duration.between(
                LocalDateTime.now(),
                LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0)
            ).getSeconds();
            
            redisUtil.set(PEAK_KEY, currentOnline, secondsUntilMidnight);
        }
    }
    
    /**
     * 计算平均在线时长
     */
    private String calculateAverageOnlineTime() {
        List<OnlineUserVO> users = getAllOnlineUsers();
        if (users.isEmpty()) {
            return "0分钟";
        }
        
        long totalSeconds = users.stream()
            .mapToLong(OnlineUserVO::getOnlineDuration)
            .sum();
        
        long avgSeconds = totalSeconds / users.size();
        
        long hours = avgSeconds / 3600;
        long minutes = (avgSeconds % 3600) / 60;
        
        if (hours > 0) {
            return String.format("%d小时%d分钟", hours, minutes);
        } else {
            return String.format("%d分钟", minutes);
        }
    }
    
    /**
     * 安全地获取Long值
     */
    private Long getLongValue(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Long) return (Long) obj;
        if (obj instanceof Integer) return ((Integer) obj).longValue();
        if (obj instanceof String) return Long.parseLong((String) obj);
        return null;
    }
    
    /**
     * 安全地获取Integer值
     */
    private Integer getIntValue(Object obj) {
        if (obj == null) return 0;
        if (obj instanceof Integer) return (Integer) obj;
        if (obj instanceof Long) return ((Long) obj).intValue();
        if (obj instanceof String) return Integer.parseInt((String) obj);
        return 0;
    }
}
