package com.zhentao.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.zhentao.common.PageResult;
import com.zhentao.dto.DynamicQueryDTO;
import com.zhentao.dto.PublishDynamicDTO;
import com.zhentao.entity.UserDynamics;
import com.zhentao.mapper.UserDynamicsMapper;
import com.zhentao.service.UserDynamicsService;
import com.zhentao.vo.DynamicVO;
import com.zhentao.vo.UserSimpleVO;
import org.springframework.beans.BeanUtils;
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.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户动态服务实现类
 */
@Service
public class UserDynamicsServiceImpl implements UserDynamicsService {

    @Autowired
    private UserDynamicsMapper userDynamicsMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final ObjectMapper objectMapper = new ObjectMapper();

    private static final String DYNAMIC_CACHE_KEY = "dynamic:detail:";
    private static final String VIEW_COUNT_KEY = "dynamic:view:";
    private static final String SYS_MSG_QUEUE = "system.message";

    @Autowired
    private com.zhentao.service.SystemMessageService systemMessageService;

    @Autowired
    private com.zhentao.mapper.DynamicReportsMapper reportMapper;

    @Autowired
    private com.zhentao.mapper.UsersMapper usersMapper;

    @Override
    public PageResult<DynamicVO> getDynamicList(DynamicQueryDTO queryDTO) {
        // 创建分页对象
        Page<UserDynamics> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        
        // 根据当前用户性别确定目标性别（推送相反性别的动态）
        Integer targetGender = null; // null表示不限制性别
        if (queryDTO.getCurrentUserId() != null) {
            try {
                com.zhentao.entity.Users currentUser = usersMapper.selectById(queryDTO.getCurrentUserId());
                if (currentUser != null && currentUser.getGender() != null) {
                    Integer currentGender = currentUser.getGender();
                    // 0-未知 1-男 2-女
                    if (currentGender == 1) {
                        // 男性用户，推送女性动态
                        targetGender = 2;
                    } else if (currentGender == 2) {
                        // 女性用户，推送男性动态
                        targetGender = 1;
                    }
                    // 如果性别是0（未知），targetGender保持为null，显示所有动态
                }
            } catch (Exception e) {
                // 如果查询用户信息失败，不限制性别，显示所有动态
                // 忽略异常，继续执行
            }
        }
        
        // 查询数据
        IPage<UserDynamics> dynamicsPage = userDynamicsMapper.selectDynamicsWithUserInfo(
                page,
                queryDTO.getCurrentUserId(),
                queryDTO.getAuditStatus() != null ? queryDTO.getAuditStatus() : 1, // 默认查询审核通过的
                queryDTO.getVisibility() != null ? queryDTO.getVisibility() : 1, // 默认查询公开的
                targetGender // 目标性别（相反性别）
        );

        // 转换为VO
        List<DynamicVO> voList = dynamicsPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        // 返回分页结果
        return new PageResult<>(voList, dynamicsPage.getTotal(), dynamicsPage.getCurrent(), dynamicsPage.getSize());
    }

    @Override
    public DynamicVO getDynamicDetail(Integer dynamicId, Integer userId) {
        // 先从缓存获取（容错）
        String cacheKey = DYNAMIC_CACHE_KEY + dynamicId + ":" + userId;
        try {
            Object cached = redisTemplate.opsForValue().get(cacheKey);
            if (cached != null) {
                return (DynamicVO) cached;
            }
        } catch (Exception ignore) {
            // ignore redis failures
        }

        // 从数据库查询
        UserDynamics dynamic = userDynamicsMapper.selectDynamicDetailById(dynamicId, userId);
        if (dynamic == null) {
            return null;
        }

        // 转换为VO
        DynamicVO vo = convertToVO(dynamic);

        // 异步增加浏览数（容错）
        increaseViewCount(dynamicId);

        // 缓存结果（5分钟，容错）
        try {
            redisTemplate.opsForValue().set(cacheKey, vo, 5, TimeUnit.MINUTES);
        } catch (Exception ignore) {
        }

        return vo;
    }

    @Override
    public PageResult<DynamicVO> getUserDynamics(DynamicQueryDTO queryDTO) {
        if (queryDTO.getTargetUserId() == null) {
            throw new IllegalArgumentException("目标用户ID不能为空");
        }

        // 创建分页对象
        Page<UserDynamics> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        // 查询数据
        IPage<UserDynamics> dynamicsPage = userDynamicsMapper.selectDynamicsByUserId(
                page,
                queryDTO.getTargetUserId(),
                queryDTO.getCurrentUserId()
        );

        // 转换为VO
        List<DynamicVO> voList = dynamicsPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        // 返回分页结果
        return new PageResult<>(voList, dynamicsPage.getTotal(), dynamicsPage.getCurrent(), dynamicsPage.getSize());
    }

    @Override
    public void increaseViewCount(Integer dynamicId) {
        // 使用Redis记录浏览数，定期同步到数据库（容错）
        String key = VIEW_COUNT_KEY + dynamicId;
        try {
            redisTemplate.opsForValue().increment(key, 1);
            redisTemplate.expire(key, 1, TimeUnit.DAYS);
        } catch (Exception ignore) {
            // ignore redis failures
        }
        // TODO: 定时任务批量同步到数据库
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean adminModerate(Integer dynamicId, Integer action, String reason) {
        if (dynamicId == null || action == null || reason == null || reason.trim().isEmpty()) {
            throw new IllegalArgumentException("参数不合法");
        }

        // 2=封禁 3=删除（沿用status逻辑：1正常，2封禁，3删除）
        int updated = userDynamicsMapper.updateDynamicStatus(dynamicId, action, reason);
        if (updated <= 0) {
            return false;
        }

        // 查询动态以获取标题和作者
        UserDynamics dynamic = userDynamicsMapper.selectById(dynamicId);
        Integer authorId = dynamic != null ? dynamic.getUserId() : null;
        String titleFull = dynamic != null ? (dynamic.getContent() == null ? "" : dynamic.getContent()) : "";
        String dynamicTitle = titleFull.length() > 20 ? titleFull.substring(0,20) + "..." : titleFull;

        // 直接落库存储系统消息（后续可扩展为MQ）——被举报人（作者）
        try {
            String type = action == 2 ? "ban" : (action == 3 ? "delete" : "unban");
            systemMessageService.sendDynamicModerationMessage(authorId, dynamicId, dynamicTitle, type, reason);
        } catch (Exception ignore) {}

        // 通知所有举报人（封禁/删除/解除封禁均发送结果通知）
        if (action == 1 || action == 2 || action == 3) {
            try {
                // 查询该动态的所有举报记录，逐个发送“举报处理结果”通知
                java.util.List<com.zhentao.entity.DynamicReports> reports =
                        reportMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<com.zhentao.entity.DynamicReports>()
                                .eq("dynamic_id", dynamicId));
                if (reports != null) {
                    String resultText = (action == 2 ? "已封禁" : (action == 3 ? "已删除" : "已解除封禁"));
                    for (com.zhentao.entity.DynamicReports r : reports) {
                        if (r.getReporterId() == null) continue;
                        String resTitle = "系统通知 - 举报处理结果";
                        String resContent = String.format("您举报的动态《%s》已被处理（%s），感谢您对社区规范的维护。", dynamicTitle, resultText);
                        systemMessageService.sendMessage(r.getReporterId(), dynamicId, resTitle, resContent, "report_result");
                    }
                }
            } catch (Exception ignore) {}
        }

        // 同时向系统消息通道发送一条通知（可供其他服务订阅）
        try {
            java.util.Map<String, Object> payload = new java.util.HashMap<>();
            String type = action == 2 ? "ban" : (action == 3 ? "delete" : "unban");
            payload.put("type", type);
            payload.put("dynamicId", dynamicId);
            payload.put("reason", reason);
            payload.put("time", java.time.LocalDateTime.now().toString());
            payload.put("authorId", authorId);
            redisTemplate.convertAndSend(SYS_MSG_QUEUE, payload);
        } catch (Exception ignore) {}

        return true;
    }

    /**
     * 将实体类转换为VO
     */
    private DynamicVO convertToVO(UserDynamics dynamic) {
        DynamicVO vo = new DynamicVO();
        BeanUtils.copyProperties(dynamic, vo);

        // 解析媒体URL JSON字符串
        if (dynamic.getMediaUrls() != null && !dynamic.getMediaUrls().isEmpty()) {
            try {
                List<String> urls = objectMapper.readValue(
                        dynamic.getMediaUrls(), 
                        new TypeReference<List<String>>() {}
                );
                vo.setMediaUrls(urls);
            } catch (Exception e) {
                vo.setMediaUrls(new ArrayList<>());
            }
        } else {
            vo.setMediaUrls(new ArrayList<>());
        }

        // 确保 isLiked 和 isFavorited 正确转换为 Boolean（根据 dynamic_likes 和 dynamic_favorites 表判断）
        // SQL 返回 1/0，MyBatis 会映射为 Boolean，但为了安全起见，确保正确转换
        Object isLikedObj = dynamic.getIsLiked();
        if (isLikedObj != null) {
            if (isLikedObj instanceof Boolean) {
                vo.setIsLiked((Boolean) isLikedObj);
            } else if (isLikedObj instanceof Integer) {
                vo.setIsLiked(((Integer) isLikedObj) == 1);
            } else if (isLikedObj instanceof Number) {
                vo.setIsLiked(((Number) isLikedObj).intValue() == 1);
            } else {
                vo.setIsLiked(Boolean.TRUE.equals(isLikedObj));
            }
        } else {
            vo.setIsLiked(false);
        }

        Object isFavoritedObj = dynamic.getIsFavorited();
        if (isFavoritedObj != null) {
            if (isFavoritedObj instanceof Boolean) {
                vo.setIsFavorited((Boolean) isFavoritedObj);
            } else if (isFavoritedObj instanceof Integer) {
                vo.setIsFavorited(((Integer) isFavoritedObj) == 1);
            } else if (isFavoritedObj instanceof Number) {
                vo.setIsFavorited(((Number) isFavoritedObj).intValue() == 1);
            } else {
                vo.setIsFavorited(Boolean.TRUE.equals(isFavoritedObj));
            }
        } else {
            vo.setIsFavorited(false);
        }

        // 转换用户信息
        if (dynamic.getUser() != null) {
            UserSimpleVO userVO = new UserSimpleVO();
            userVO.setUserId(dynamic.getUser().getUserId());
            userVO.setNickname(dynamic.getUser().getNickname());
            userVO.setAvatarUrl(dynamic.getUser().getAvatarUrl());
            userVO.setGender(dynamic.getUser().getGender());
            vo.setUser(userVO);
        }

        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createUserDynamic(PublishDynamicDTO dto) {
        if (dto.getUserId() == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (dto.getContent() == null || dto.getContent().trim().isEmpty()) {
            throw new IllegalArgumentException("动态内容不能为空");
        }

        UserDynamics dynamic = new UserDynamics();
        dynamic.setUserId(dto.getUserId());
        dynamic.setContent(dto.getContent());
        dynamic.setMediaType(dto.getMediaType() == null ? 1 : dto.getMediaType());
        dynamic.setVisibility(dto.getVisibility() == null ? 1 : dto.getVisibility());
        dynamic.setAuditStatus(1); // 默认审核通过
        dynamic.setStatus(1); // 正常状态
        dynamic.setLikeCount(0);
        dynamic.setCommentCount(0);
        dynamic.setFavoriteCount(0);
        dynamic.setShareCount(0);
        dynamic.setViewCount(0);
        dynamic.setCreatedAt(LocalDateTime.now());
        dynamic.setUpdatedAt(LocalDateTime.now());

        // 处理媒体URL列表
        if (CollectionUtils.isNotEmpty(dto.getMediaList())) {
            try {
                dynamic.setMediaUrls(objectMapper.writeValueAsString(dto.getMediaList()));
            } catch (JsonProcessingException e) {
                throw new RuntimeException("媒体URL序列化失败", e);
            }
        }

        userDynamicsMapper.insert(dynamic);
        return dynamic.getDynamicId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserDynamic(Integer dynamicId, Integer userId, PublishDynamicDTO dto) {
        if (dynamicId == null || userId == null) {
            throw new IllegalArgumentException("动态ID和用户ID不能为空");
        }

        // 验证动态是否存在且属于该用户
        UserDynamics existing = userDynamicsMapper.selectById(dynamicId);
        if (existing == null) {
            throw new IllegalArgumentException("动态不存在");
        }
        if (!existing.getUserId().equals(userId)) {
            throw new IllegalArgumentException("无权修改该动态");
        }
        if (existing.getStatus() != 1) {
            throw new IllegalArgumentException("该动态已被删除或封禁，无法修改");
        }

        // 更新动态信息
        UpdateWrapper<UserDynamics> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("dynamic_id", dynamicId)
                .eq("user_id", userId); // 确保只能修改自己的动态

        if (dto.getContent() != null) {
            updateWrapper.set("content", dto.getContent());
        }
        if (dto.getMediaType() != null) {
            updateWrapper.set("media_type", dto.getMediaType());
        }
        if (dto.getVisibility() != null) {
            updateWrapper.set("visibility", dto.getVisibility());
        }
        if (dto.getMediaList() != null) {
            try {
                String mediaUrlsJson = CollectionUtils.isNotEmpty(dto.getMediaList()) 
                    ? objectMapper.writeValueAsString(dto.getMediaList()) 
                    : null;
                updateWrapper.set("media_urls", mediaUrlsJson);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("媒体URL序列化失败", e);
            }
        }
        updateWrapper.set("updated_at", LocalDateTime.now());

        int updated = userDynamicsMapper.update(null, updateWrapper);
        
        // 清除缓存（清除所有可能的用户缓存）
        if (updated > 0) {
            try {
                String pattern = DYNAMIC_CACHE_KEY + dynamicId + ":*";
                java.util.Set<String> keys = redisTemplate.keys(pattern);
                if (keys != null && !keys.isEmpty()) {
                    redisTemplate.delete(keys);
                }
            } catch (Exception ignore) {
                // 忽略缓存清除失败
            }
        }

        return updated > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUserDynamic(Integer dynamicId, Integer userId) {
        if (dynamicId == null || userId == null) {
            throw new IllegalArgumentException("动态ID和用户ID不能为空");
        }

        // 验证动态是否存在且属于该用户
        UserDynamics existing = userDynamicsMapper.selectById(dynamicId);
        if (existing == null) {
            throw new IllegalArgumentException("动态不存在");
        }
        if (!existing.getUserId().equals(userId)) {
            throw new IllegalArgumentException("无权删除该动态");
        }

        // 逻辑删除（使用MyBatis-Plus的逻辑删除）
        UpdateWrapper<UserDynamics> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("dynamic_id", dynamicId)
                .eq("user_id", userId) // 确保只能删除自己的动态
                .set("status", 0) // 0表示删除
                .set("updated_at", LocalDateTime.now());

        int deleted = userDynamicsMapper.update(null, updateWrapper);
        
        // 清除缓存（清除所有可能的用户缓存）
        if (deleted > 0) {
            try {
                String pattern = DYNAMIC_CACHE_KEY + dynamicId + ":*";
                java.util.Set<String> keys = redisTemplate.keys(pattern);
                if (keys != null && !keys.isEmpty()) {
                    redisTemplate.delete(keys);
                }
            } catch (Exception ignore) {
                // 忽略缓存清除失败
            }
        }

        return deleted > 0;
    }
}


