package com.zhentao.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.constant.RedisKeyConstants;
import com.zhentao.dto.MatchmakerQueryDTO;
import com.zhentao.entity.Matchmaker;
import com.zhentao.entity.MatchmakerLike;
import com.zhentao.mapper.MatchmakerMapper;
import com.zhentao.mapper.MatchmakerLikeMapper;
import com.zhentao.service.MatchmakerService;
import com.zhentao.util.MinioUtil;
import com.zhentao.vo.MatchmakerVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 红娘服务实现类（带Redis缓存）
 */
@Service
public class MatchmakerServiceImpl extends ServiceImpl<MatchmakerMapper, Matchmaker> implements MatchmakerService {
    
    @Autowired
    private MatchmakerMapper matchmakerMapper;
    
    @Autowired
    private MatchmakerLikeMapper matchmakerLikeMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private MinioUtil minioUtil;
    
    @Override
    @SuppressWarnings("unchecked")
    public Page<MatchmakerVO> getMatchmakerPage(MatchmakerQueryDTO queryDTO) {
        // 1. 构建缓存Key（包含keyword参数）
        String cacheKey = RedisKeyConstants.buildMatchmakerListKey(
                queryDTO.getMatchmakerType(),
                queryDTO.getLevel(),
                queryDTO.getProvinceId(),
                queryDTO.getCityId(),
                queryDTO.getKeyword(),
                queryDTO.getPageNum(),
                queryDTO.getPageSize()
        );
        
        // 2. 尝试从Redis获取缓存（带异常处理）
        try {
            Page<MatchmakerVO> cachedPage = (Page<MatchmakerVO>) redisTemplate.opsForValue().get(cacheKey);
            if (cachedPage != null) {
                // 检查缓存数据是否异常：如果total为0但records不为空，说明缓存数据有问题，需要清除缓存
                if (cachedPage.getTotal() == 0 && cachedPage.getRecords() != null && !cachedPage.getRecords().isEmpty()) {
                    System.out.println("⚠️ 检测到缓存数据异常（total=0但records不为空），清除缓存并重新查询: " + cacheKey);
                    redisTemplate.delete(cacheKey);
                    // 继续执行数据库查询
                } else {
                    System.out.println("✅ 从Redis缓存获取红娘列表: " + cacheKey + ", total=" + cachedPage.getTotal() + ", records=" + cachedPage.getRecords().size());
                    return cachedPage;
                }
            }
        } catch (Exception e) {
            System.err.println("⚠️ Redis读取失败，将直接查询数据库: " + e.getMessage());
        }
        
        // 3. 缓存未命中或Redis异常，从数据库查询
        System.out.println("📊 从数据库查询红娘列表: " + cacheKey);
        Page<MatchmakerVO> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        
        Page<MatchmakerVO> result = matchmakerMapper.selectMatchmakerPage(
                page,
                queryDTO.getMatchmakerType(),
                queryDTO.getLevel(),
                queryDTO.getProvinceId(),
                queryDTO.getCityId(),
                queryDTO.getKeyword(),
                queryDTO.getOrderBy(),
                queryDTO.getOrderType()
        );
        
        // 4. 处理数据
        result.getRecords().forEach(this::processMatchmakerVO);
        
        // 5. 打印查询结果日志
        System.out.println("📈 查询结果 - total: " + result.getTotal() + ", records: " + result.getRecords().size() + ", current: " + result.getCurrent() + ", size: " + result.getSize());
        
        // 6. 尝试存入Redis缓存（带异常处理）
        try {
            redisTemplate.opsForValue().set(
                    cacheKey, 
                    result, 
                    RedisKeyConstants.MATCHMAKER_LIST_EXPIRE, 
                    TimeUnit.SECONDS
            );
            System.out.println("💾 红娘列表已缓存到Redis: " + cacheKey);
        } catch (Exception e) {
            System.err.println("⚠️ Redis写入失败，但不影响查询结果: " + e.getMessage());
        }
        
        return result;
    }
    
    @Override
    public MatchmakerVO getMatchmakerDetail(Integer matchmakerId) {
        // 1. 构建缓存Key
        String cacheKey = RedisKeyConstants.buildMatchmakerDetailKey(matchmakerId);
        
        // 2. 尝试从Redis获取缓存（带异常处理）
        try {
            MatchmakerVO cachedVO = (MatchmakerVO) redisTemplate.opsForValue().get(cacheKey);
            if (cachedVO != null) {
                System.out.println("✅ 从Redis缓存获取红娘详情: " + cacheKey);
                return cachedVO;
            }
        } catch (Exception e) {
            System.err.println("⚠️ Redis读取失败，将直接查询数据库: " + e.getMessage());
        }
        
        // 3. 缓存未命中或Redis异常，从数据库查询
        System.out.println("❌ 缓存未命中或Redis异常，从数据库查询: " + cacheKey);
        MatchmakerVO matchmakerVO = matchmakerMapper.selectMatchmakerDetail(matchmakerId);
        
        if (matchmakerVO != null) {
            // 4. 处理数据
            processMatchmakerVO(matchmakerVO);
            
            // 5. 尝试存入Redis缓存（带异常处理）
            try {
                redisTemplate.opsForValue().set(
                        cacheKey, 
                        matchmakerVO, 
                        RedisKeyConstants.MATCHMAKER_DETAIL_EXPIRE, 
                        TimeUnit.SECONDS
                );
                System.out.println("💾 红娘详情已缓存到Redis: " + cacheKey);
            } catch (Exception e) {
                System.err.println("⚠️ Redis写入失败，但不影响查询结果: " + e.getMessage());
            }
        }
        
        return matchmakerVO;
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public Page<MatchmakerVO> getFormalMatchmakers(Integer pageNum, Integer pageSize) {
        // 1. 构建缓存Key
        String cacheKey = RedisKeyConstants.buildFormalListKey(pageNum, pageSize);
        
        // 2. 尝试从Redis获取缓存（带异常处理）
        try {
            Page<MatchmakerVO> cachedPage = (Page<MatchmakerVO>) redisTemplate.opsForValue().get(cacheKey);
            if (cachedPage != null) {
                System.out.println("✅ 从Redis缓存获取全职红娘列表: " + cacheKey);
                return cachedPage;
            }
        } catch (Exception e) {
            System.err.println("⚠️ Redis读取失败，将直接查询数据库: " + e.getMessage());
        }
        
        // 3. 缓存未命中或Redis异常，查询数据库
        System.out.println("❌ 缓存未命中或Redis异常，从数据库查询: " + cacheKey);
        MatchmakerQueryDTO queryDTO = new MatchmakerQueryDTO();
        queryDTO.setMatchmakerType(2); // 2-全职
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setOrderBy("success_couples");
        queryDTO.setOrderType("desc");
        
        Page<MatchmakerVO> result = getMatchmakerPage(queryDTO);
        
        // 4. 尝试单独缓存全职红娘列表（带异常处理）
        try {
            redisTemplate.opsForValue().set(
                    cacheKey, 
                    result, 
                    RedisKeyConstants.MATCHMAKER_HOT_EXPIRE, 
                    TimeUnit.SECONDS
            );
            System.out.println("💾 全职红娘列表已缓存到Redis: " + cacheKey);
        } catch (Exception e) {
            System.err.println("⚠️ Redis写入失败，但不影响查询结果: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 处理红娘VO数据
     * 
     * @param vo 红娘VO
     */
    private void processMatchmakerVO(MatchmakerVO vo) {
        // 计算年龄
        if (vo.getBirthDate() != null) {
            LocalDate now = LocalDate.now();
            Period period = Period.between(vo.getBirthDate(), now);
            vo.setAge(period.getYears());
        }
        
        // 设置性别名称
        if (vo.getGender() != null) {
            vo.setGenderName(vo.getGender() == 1 ? "男" : "女");
        }
        
        // 设置类型名称
        if (vo.getMatchmakerType() != null) {
            vo.setTypeName(vo.getMatchmakerType() == 1 ? "兼职红娘" : "全职红娘");
        }
        
        // 处理积分和等级进度
        if (vo.getPoints() != null) {
            Integer points = vo.getPoints();
            Integer level = 1; // 默认等级为青铜
            
            // 根据积分区间设置等级（历史总积分用于等级判断）
            // 积分0-500是青铜(1)
            if (points <= 500) {
                level = 1;
            }
            // 501-1000是白金(2)
            else if (points <= 1000) {
                level = 2;
            }
            // 1001-1500是黄金(3)
            else if (points <= 1500) {
                level = 3;
            }
            // 1501到2000是铂金(4)
            else if (points <= 2000) {
                level = 4;
            }
            // 2000以上是钻石(5)
            else {
                level = 5;
            }
            
            // 更新VO中的等级
            vo.setLevel(level);
            
            // 设置等级名称
            switch (level) {
                case 1:
                    vo.setLevelName("青铜红娘");
                    break;
                case 2:
                    vo.setLevelName("白金红娘");
                    break;
                case 3:
                    vo.setLevelName("黄金红娘");
                    break;
                case 4:
                    vo.setLevelName("铂金红娘");
                    break;
                case 5:
                    vo.setLevelName("钻石红娘");
                    break;
                default:
                    vo.setLevelName("青铜红娘");
            }
            
            // 等级积分规则（历史总积分用于等级判断）
            int[] levelPoints = {0, 500, 1000, 1500, 2000, Integer.MAX_VALUE};
            
            // 设置当前等级和下一等级所需积分
            vo.setCurrentLevelPoints(levelPoints[level - 1]);
            vo.setNextLevelPoints(levelPoints[level]);
            
            // 计算升级还需积分
            int pointsToNext = vo.getNextLevelPoints() - points;
            vo.setPointsToNextLevel(pointsToNext > 0 ? pointsToNext : 0);
            
            // 计算等级进度百分比（优化：显示在当前等级区间内的进度）
            int progress = 0;
            int levelRange = vo.getNextLevelPoints() - vo.getCurrentLevelPoints();
            if (levelRange > 0) {
                // 计算当前积分在当前等级区间内的进度，更合理
                int currentInLevel = points - vo.getCurrentLevelPoints();
                progress = (int) Math.round(((double) currentInLevel / levelRange) * 100);
                // 确保进度在0-100%之间
                progress = Math.max(0, Math.min(progress, 100));
            } else {
                progress = 100;
            }
            vo.setLevelProgress(progress);
        }
        
        // 设置红娘评分（暂时固定为5.0，后续可根据实际业务逻辑计算）
        vo.setRating(5.0);
        
        // 拼接完整地址
        StringBuilder fullAddress = new StringBuilder();
        if (vo.getProvinceName() != null) {
            fullAddress.append(vo.getProvinceName());
        }
        if (vo.getCityName() != null) {
            fullAddress.append(vo.getCityName());
        }
        if (vo.getAreaName() != null) {
            fullAddress.append(vo.getAreaName());
        }
        if (vo.getAddressDetail() != null) {
            fullAddress.append(vo.getAddressDetail());
        }
        vo.setFullAddress(fullAddress.toString());
        
        // 从MinIO获取头像URL（降低数据库查询压力）
        // 数据库中的avatar_url字段可以存储文件名，如：红娘1.jpg
        if (vo.getAvatarUrl() != null && !vo.getAvatarUrl().isEmpty()) {
            // 如果数据库存储的不是完整URL（不是http开头），从MinIO获取访问URL
            if (!vo.getAvatarUrl().startsWith("http")) {
                String minioUrl = minioUtil.getMatchmakerAvatarUrl(vo.getMatchmakerId(), vo.getAvatarUrl());
                vo.setAvatarUrl(minioUrl);
            }
            // 如果已经是完整URL（http开头），保持原URL不变，无需处理
        } else {
            // 数据库没有存储文件名，尝试根据红娘ID自动匹配
            String minioUrl = minioUtil.getMatchmakerAvatarUrlById(vo.getMatchmakerId());
            vo.setAvatarUrl(minioUrl);
        }
    }
    
    /**
     * 清除红娘相关缓存（用于数据更新时）
     * 
     * @param matchmakerId 红娘ID，如果为null则只清除列表缓存
     */
    public void clearMatchmakerCache(Integer matchmakerId) {
        try {
            // 如果有matchmakerId，清除红娘详情缓存
            if (matchmakerId != null) {
                String detailKey = RedisKeyConstants.buildMatchmakerDetailKey(matchmakerId);
                redisTemplate.delete(detailKey);
                System.out.println("🗑️ 已清除红娘详情缓存: matchmakerId=" + matchmakerId);
            }
            
            // 清除列表缓存（使用模糊匹配删除）
            Set<String> listKeys = redisTemplate.keys(RedisKeyConstants.MATCHMAKER_LIST + "*");
            if (listKeys != null && !listKeys.isEmpty()) {
                redisTemplate.delete(listKeys);
                System.out.println("🗑️ 已清除红娘列表缓存: " + listKeys.size() + " 个");
            }
            
            // 清除全职红娘列表缓存
            Set<String> formalKeys = redisTemplate.keys(RedisKeyConstants.MATCHMAKER_FORMAL_LIST + "*");
            if (formalKeys != null && !formalKeys.isEmpty()) {
                redisTemplate.delete(formalKeys);
                System.out.println("🗑️ 已清除全职红娘列表缓存: " + formalKeys.size() + " 个");
            }
            
            System.out.println("✅ 缓存清除完成");
        } catch (Exception e) {
            System.err.println("⚠️ 清除Redis缓存失败，但不影响数据更新: " + e.getMessage());
        }
    }
    
    @Override
    public MatchmakerVO getMatchmakerByUserId(Long userId) {
        // 1. 构建缓存Key
        String cacheKey = RedisKeyConstants.MATCHMAKER_LIST + "user:" + userId;
        
        // 2. 尝试从Redis获取缓存（带异常处理）
        try {
            MatchmakerVO cachedVO = (MatchmakerVO) redisTemplate.opsForValue().get(cacheKey);
            if (cachedVO != null) {
                System.out.println("✅ 从Redis缓存获取红娘详情: " + cacheKey + ", 积分: " + cachedVO.getPoints());
                // 为了解决缓存数据不一致问题，临时移除缓存，直接查询数据库
                redisTemplate.delete(cacheKey);
                System.out.println("🗑️ 已清除旧的Redis缓存: " + cacheKey);
            }
        } catch (Exception e) {
            System.err.println("⚠️ Redis读取失败，将直接查询数据库: " + e.getMessage());
        }
        
        // 3. 从数据库查询最新数据
        System.out.println("❌ 从数据库查询最新红娘详情: " + cacheKey);
        MatchmakerVO matchmakerVO = matchmakerMapper.selectMatchmakerByUserId(userId);
        
        if (matchmakerVO != null) {
            // 4. 处理数据
            processMatchmakerVO(matchmakerVO);
            System.out.println("📊 数据库查询结果，积分: " + matchmakerVO.getPoints());
            
            // 5. 尝试存入Redis缓存（带异常处理）
            try {
                redisTemplate.opsForValue().set(
                        cacheKey, 
                        matchmakerVO, 
                        60, // 缩短缓存时间为60秒，减少数据不一致的影响
                        TimeUnit.SECONDS
                );
                System.out.println("💾 最新红娘详情已缓存到Redis: " + cacheKey + ", 积分: " + matchmakerVO.getPoints());
            } catch (Exception e) {
                System.err.println("⚠️ Redis写入失败，但不影响查询结果: " + e.getMessage());
            }
        }
        
        return matchmakerVO;
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public List<MatchmakerVO> getRankingList(Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 20;
        }
        
        // 1. 构建缓存Key
        String cacheKey = RedisKeyConstants.MATCHMAKER_LIST + "ranking:" + limit;
        
        // 2. 尝试从Redis获取缓存
        try {
            List<MatchmakerVO> cachedList = (List<MatchmakerVO>) redisTemplate.opsForValue().get(cacheKey);
            if (cachedList != null) {
                System.out.println("✅ 从Redis缓存获取红娘排行榜: " + cacheKey);
                return cachedList;
            }
        } catch (Exception e) {
            System.err.println("⚠️ Redis读取失败，将直接查询数据库: " + e.getMessage());
        }
        
        // 3. 缓存未命中，从数据库查询
        System.out.println("❌ 缓存未命中，从数据库查询排行榜");
        List<MatchmakerVO> rankingList = matchmakerMapper.selectRankingList(limit);
        
        // 4. 处理数据
        rankingList.forEach(this::processMatchmakerVO);
        
        // 5. 尝试存入Redis缓存（缓存1小时）
        try {
            redisTemplate.opsForValue().set(cacheKey, rankingList, 3600, TimeUnit.SECONDS);
            System.out.println("💾 红娘排行榜已缓存到Redis: " + cacheKey);
        } catch (Exception e) {
            System.err.println("⚠️ Redis写入失败: " + e.getMessage());
        }
        
        return rankingList;
    }
    
    @Override
    public Matchmaker getMatchmakerByUserId(Integer userId) {
        // 根据 user_id 查询红娘信息
        return this.lambdaQuery()
                .eq(Matchmaker::getUserId, userId.longValue())
                .one();
    }
    
    @Override
    public List<MatchmakerVO> batchGetMatchmakers(List<Integer> matchmakerIds) {
        if (matchmakerIds == null || matchmakerIds.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 批量查询红娘详情
        List<MatchmakerVO> matchmakers = matchmakerMapper.selectBatchMatchmakers(matchmakerIds);
        
        // 处理数据（计算年龄、处理头像等）
        matchmakers.forEach(this::processMatchmakerVO);
        
        return matchmakers;
    }
    
    /**
     * 获取当前周的标识（格式：yyyy-ww）
     */
    private String getCurrentWeekKey() {
        LocalDate now = LocalDate.now();
        WeekFields weekFields = WeekFields.of(Locale.CHINA);
        int weekNumber = now.get(weekFields.weekOfWeekBasedYear());
        int year = now.get(weekFields.weekBasedYear());
        return String.format("%d-%02d", year, weekNumber);
    }
    
    @Override
    public boolean hasLikedThisWeek(Long userId, Long matchmakerId) {
        String weekKey = getCurrentWeekKey();
        int count = matchmakerLikeMapper.countByUserAndMatchmakerAndWeek(userId, matchmakerId, weekKey);
        return count > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean likeMatchmaker(Long userId, Long matchmakerId) {
        // 1. 检查本周是否已点赞
        if (hasLikedThisWeek(userId, matchmakerId)) {
            return false; // 本周已点赞过
        }
        
        // 2. 插入点赞记录
        String weekKey = getCurrentWeekKey();
        MatchmakerLike like = new MatchmakerLike();
        like.setUserId(userId);
        like.setMatchmakerId(matchmakerId);
        like.setLikeTime(LocalDateTime.now());
        like.setWeekKey(weekKey);
        matchmakerLikeMapper.insert(like);
        
        // 3. 更新红娘总点赞数
        Matchmaker matchmaker = this.getById(matchmakerId);
        if (matchmaker != null) {
            Integer currentLikes = matchmaker.getLikes() != null ? matchmaker.getLikes() : 0;
            matchmaker.setLikes(currentLikes + 1);
            this.updateById(matchmaker);
        }
        
        // 4. 清除排行榜缓存
        try {
            Set<String> keys = redisTemplate.keys(RedisKeyConstants.MATCHMAKER_LIST + "ranking:*");
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
            }
            // 清除本周排行榜缓存
            redisTemplate.delete(RedisKeyConstants.MATCHMAKER_LIST + "weekly_ranking:" + weekKey + ":*");
        } catch (Exception e) {
            System.err.println("⚠️ 清除排行榜缓存失败: " + e.getMessage());
        }
        
        return true;
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public List<MatchmakerVO> getWeeklyRankingList(Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 20;
        }
        
        String weekKey = getCurrentWeekKey();
        String cacheKey = RedisKeyConstants.MATCHMAKER_LIST + "weekly_ranking:" + weekKey + ":" + limit;
        
        // 1. 尝试从缓存获取
        try {
            List<MatchmakerVO> cachedList = (List<MatchmakerVO>) redisTemplate.opsForValue().get(cacheKey);
            if (cachedList != null) {
                System.out.println("✅ 从Redis缓存获取本周红娘排行榜: " + cacheKey);
                return cachedList;
            }
        } catch (Exception e) {
            System.err.println("⚠️ Redis读取失败: " + e.getMessage());
        }
        
        // 2. 从数据库查询所有活跃红娘
        System.out.println("❌ 缓存未命中，从数据库查询本周排行榜");
        List<MatchmakerVO> allMatchmakers = matchmakerMapper.selectRankingList(100); // 获取更多数据用于计算
        
        // 3. 计算本周点赞数并设置到VO
        for (MatchmakerVO vo : allMatchmakers) {
            int weeklyLikes = matchmakerLikeMapper.countWeeklyLikes(vo.getMatchmakerId().longValue(), weekKey);
            vo.setWeeklyLikes(weeklyLikes);
            
            // 计算排名分数：(本周点赞数 + 成功人数) / 2
            int successCouples = vo.getSuccessCouples() != null ? vo.getSuccessCouples() : 0;
            double rankScore = (weeklyLikes + successCouples) / 2.0;
            vo.setRankScore(rankScore);
        }
        
        // 4. 按排名分数降序排序
        List<MatchmakerVO> rankingList = allMatchmakers.stream()
                .sorted(Comparator.comparingDouble(MatchmakerVO::getRankScore).reversed())
                .limit(limit)
                .collect(Collectors.toList());
        
        // 5. 处理数据
        rankingList.forEach(this::processMatchmakerVO);
        
        // 6. 缓存结果（缓存10分钟）
        try {
            redisTemplate.opsForValue().set(cacheKey, rankingList, 600, TimeUnit.SECONDS);
            System.out.println("💾 本周红娘排行榜已缓存到Redis: " + cacheKey);
        } catch (Exception e) {
            System.err.println("⚠️ Redis写入失败: " + e.getMessage());
        }
        
        return rankingList;
    }
}
