package com.tourism.webadmin.app.website.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.tourism.common.additional.config.ApplicationConfig;
import com.tourism.common.additional.utils.UrlConvertUtils;
import com.tourism.common.core.annotation.MyRequestBody;
import com.tourism.common.core.constant.ErrorCodeEnum;
import com.tourism.common.core.object.MyOrderParam;
import com.tourism.common.core.object.MyPageData;
import com.tourism.common.core.object.ResponseResult;
import com.tourism.common.core.object.TokenData;
import com.tourism.common.core.util.MyCommonUtil;
import com.tourism.common.core.util.MyModelUtil;
import com.tourism.common.core.util.MyPageUtil;
import com.tourism.common.log.annotation.OperationLog;
import com.tourism.common.log.model.constant.SysOperationLogType;
import com.tourism.webadmin.app.website.dto.TravelNotesCommentToWebDto;
import com.tourism.webadmin.app.website.vo.CollectCommentsVo;
import com.tourism.webadmin.app.website.vo.TravelNotesCommentVo;
import com.tourism.webadmin.back.dto.TourTravelNotesCommentDto;
import com.tourism.webadmin.back.model.*;
import com.tourism.webadmin.back.service.*;
import com.tourism.webadmin.back.vo.TourTravelNotesCommentVo;
import com.tourism.webadmin.back.vo.TourismProjectTravelNotesWriteVo;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 游记评论操作控制器类。
 *
 * @author 吃饭睡觉
 * @date 2024-09-06
 */
@Tag(name = "游记评论门户接口")
@Slf4j
@RestController
@RequestMapping("/website/comment/tourTravelNotesComment")
public class TravelNotesCommentController {

    @Autowired
    private TourTravelNotesCommentService tourTravelNotesCommentService;
    @Autowired
    private ApplicationConfig applicationConfig;
    @Autowired
    private TourismProjectTravelNotesWriteService tourismProjectTravelNotesWriteService;
    @Autowired
    private TourUserCommentCollectRelationService tourUserCommentCollectRelationService;
    @Autowired
    private TourUserCommentLikeRelationService tourUserCommentLikeRelationService;
    @Autowired
    private TourUserService tourUserService;

    /**
     * 新增游记评论数据。
     *
     * @param tourTravelNotesCommentDto 新增对象。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @ApiOperationSupport(ignoreParameters = {"tourTravelNotesCommentDto.id"})
    @OperationLog(type = SysOperationLogType.ADD)
    @PostMapping("/add")
    public ResponseResult<String> add(@RequestBody TourTravelNotesCommentDto tourTravelNotesCommentDto){
        String errorMessage = MyCommonUtil.getModelValidationError(tourTravelNotesCommentDto, false);
        if (errorMessage != null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        TourTravelNotesComment tourTravelNotesComment = MyModelUtil.copyTo(tourTravelNotesCommentDto, TourTravelNotesComment.class);
        tourTravelNotesCommentService.saveNewComment(tourTravelNotesComment);

        return ResponseResult.success(tourTravelNotesComment.getId());
    }

    /**
     * 删除游记评论数据。
     *
     * @param id 删除对象主键Id。
     * @return 应答结果对象。
     */
    @OperationLog(type = SysOperationLogType.DELETE)
    @PostMapping("/delete")
    public ResponseResult<Void> delete(@MyRequestBody Long id) {
        if (MyCommonUtil.existBlankArgument(id)) {
            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
        }
        return this.doDelete(id);
    }

    /**
     * 列出符合过滤条件的游记评论列表。
     *
     * @param dto 过滤对象、排序参数、分页参数。
     * @return 应答结果对象，包含查询结果集。
     */
    @SaIgnore
    @GetMapping("/list")
    public ResponseResult<TravelNotesCommentVo> list(TravelNotesCommentToWebDto dto) {

        TravelNotesCommentVo travelNotesCommentVo = new TravelNotesCommentVo();
//        if (dto != null) {
//            PageMethod.startPage(dto.getPageNum(), dto.getPageSize(), dto.getCount());
//        }
        TourTravelNotesComment tourTravelNotesCommentFilter = MyModelUtil.copyTo(dto, TourTravelNotesComment.class);
        tourTravelNotesCommentFilter.setTravelNoteId(Long.valueOf(dto.getTravelNoteId()));

        MyOrderParam myOrderParam = new MyOrderParam();
        myOrderParam.add(new MyOrderParam.OrderInfo("createTime",true,null));
        String orderBy = MyOrderParam.buildOrderBy(myOrderParam, TourTravelNotesComment.class);
        //该游记的全部评论
        List<TourTravelNotesComment> commentList =
                tourTravelNotesCommentService.getTourTravelNotesCommentListWithRelation(tourTravelNotesCommentFilter, orderBy);
        //游记下的全部评论ids
        List<String> collect1 = commentList.stream().map(TourTravelNotesComment::getId).collect(Collectors.toList());

        if(CollectionUtils.isNotEmpty(commentList)) {
            // commentList转为TourTravelNotesCommentVo类型list
            List<TourTravelNotesCommentVo> commentVoList = MyModelUtil.copyCollectionTo(commentList, TourTravelNotesCommentVo.class);

            TokenData tokenData = TokenData.takeFromRequest();
            if (tokenData != null) {
                Long userId = tokenData.getUserId();
                // 评论是否为当前用户
                List<TourTravelNotesCommentVo> commentVos = commentVoList.stream().filter(e -> e.getCreateUserId().equals(userId)).toList();
                commentVos.forEach(e -> {
                    e.setSelf(true);
                });
                //全部评论
                List<TourUserCommentCollectRelation> list = tourUserCommentCollectRelationService.lambdaQuery().in(TourUserCommentCollectRelation::getCommentId, collect1).list();
                QueryWrapper<TourUserCommentCollectRelation> query = new QueryWrapper<>();

                query.select(" count(user_id) as count ,comment_id as commentId")
                        .groupBy("comment_id");
                List<Map<String, Object>> maps = tourUserCommentCollectRelationService.getBaseMapper().selectMaps(query);
                //评论id->收藏数量
                HashMap<String, Integer> count = new HashMap<>();

                for (Map<String, Object> map : maps) {
                    String id =map.get("commentId").toString();
                    Integer num =Integer.valueOf(map.get("count").toString());
                    count.put(id,num);
                }
                for (TourTravelNotesCommentVo tourTravelNotesCommentVo : commentVoList) {
                    Integer i = count.get(tourTravelNotesCommentVo.getId());
                    if(i!=null){
                        tourTravelNotesCommentVo.setCollectNum(i);
                    }
                }
                //查看自己是否收藏该评论
                //获取所有评论的id
                //获取自己收藏的评论
                TourUserCommentCollectRelation tourUserCommentCollectRelation = new TourUserCommentCollectRelation();
                tourUserCommentCollectRelation.setUserId(userId);
                List<TourUserCommentCollectRelation> tourUserCommentCollectRelationList
                        = tourUserCommentCollectRelationService.getTourUserCommentCollectRelationList(tourUserCommentCollectRelation, "");
                //收藏的评论ids
                List<Long> collectCommentIdList = tourUserCommentCollectRelationList.stream().map(TourUserCommentCollectRelation::getCommentId).collect(Collectors.toList());

                //查看自己是否对该评论进行点赞了
                //获取自己点赞的所有评论id
                TourUserCommentLikeRelation tourUserCommentLikeRelation = new TourUserCommentLikeRelation();
                tourUserCommentLikeRelation.setUserId(userId);
                List<TourUserCommentLikeRelation> tourUserCommentLikeRelationList =
                        tourUserCommentLikeRelationService.getTourUserCommentLikeRelationList(tourUserCommentLikeRelation, "");
                //用户点赞的评论id
                List<Long> likeCommentIdList = tourUserCommentLikeRelationList.stream().map(TourUserCommentLikeRelation::getCommentId).collect(Collectors.toList());
                commentVoList.stream().forEach(item -> {
                    //遍历所有的评论，筛选出哪些是用户已经收藏的评论
                    if (collectCommentIdList.contains(Long.valueOf(item.getId()))) {
                        item.setIsCollect(1);
                    }else {
                        item.setIsCollect(0);
                    }
                    //遍历所有的点赞评论，筛选出哪些是用户已经点赞的评论
                    if (likeCommentIdList.contains(Long.valueOf(item.getId()))) {
                        item.setIsLike(1);
                    }else {
                        item.setIsLike(0);
                    }
                });

            }


            // 一级评论和二级评论分开
            List<TourTravelNotesCommentVo> firstCommentList = commentVoList.stream().filter(e -> e.getParentId() == null).toList();
            List<TourTravelNotesCommentVo> secondCommentList = commentVoList.stream().filter(e -> e.getParentId() != null).toList();
            // 二级评论做map数据
            Map<String, List<TourTravelNotesCommentVo>> collect = secondCommentList.stream().collect(Collectors.groupingBy(e -> e.getParentId()));
            // 作为子评论追加到一级评论
            firstCommentList.forEach(e -> {
                List<TourTravelNotesCommentVo> childList = collect.get(e.getId());
                if (childList != null && childList.size() > 0) {
                    e.setChildrenList(childList);
                }
            });
            travelNotesCommentVo.setCommentCount(commentList.size());
            travelNotesCommentVo.setTourTravelNotesCommentVoList(firstCommentList);
        }
        return ResponseResult.success(travelNotesCommentVo);
    }

    /**
     * 我的评论
     * @param dto
     * @return
     */
//    @SaIgnore
    @GetMapping("/my-comments")
    public ResponseResult<MyPageData<TourTravelNotesCommentVo>> myComments(TravelNotesCommentToWebDto dto) {
        if(dto.getCommentType() == null){
            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
        }

        List<TourTravelNotesComment> list = tourTravelNotesCommentService.getMyTravelNoteComments(dto);
        list.forEach(e->{
            Map<String, Object> travelNoteDictMap = e.getTravelNoteDictMap();
            String url = null;
            if(travelNoteDictMap != null){
                url = (String)travelNoteDictMap.get("name");
            }
            e.setTravelNoteUrl(UrlConvertUtils.urlConvertSingle(applicationConfig.getHostIpPort(), url));
        });
        MyPageData<TourTravelNotesCommentVo> tourTravelNotesCommentVoMyPageData = MyPageUtil.makeResponseData(list, TourTravelNotesCommentVo.class);
        return ResponseResult.success(tourTravelNotesCommentVoMyPageData);
    }

    private ResponseResult<Void> doDelete(Long id) {
        String errorMessage;
        // 验证关联Id的数据合法性
        TourTravelNotesComment comment = tourTravelNotesCommentService.getById(id);
        if (comment == null) {
            errorMessage = "数据验证失败，当前评论并不存在，请刷新后重试！";
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
        }
        if (!tourTravelNotesCommentService.remove(id)) {
            errorMessage = "数据操作失败，删除的对象不存在，请刷新后重试！";
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
        }
        // 删除评论后，判断是不是一级评论，如果是，则删除子评论
        if (MyCommonUtil.isBlankOrNull(comment.getParentId())) {
            tourTravelNotesCommentService.deleteChildrenComment(Long.parseLong(comment.getId()));
        }
        return ResponseResult.success();
    }
    //对评论进行点赞
    /**
     * 对评论进行点赞。
     *
     * @param commentId 评论id。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @OperationLog(type = SysOperationLogType.ADD)
    @PostMapping("/commentLike")
    @Transactional
    public ResponseResult<Void> commentLike(@RequestBody Long commentId){
        TourTravelNotesComment byId = tourTravelNotesCommentService.getById(commentId);
        if(byId==null){
            return ResponseResult.error("500","评论不存在");
        }
        //判断是否已经点赞
        List<TourUserCommentLikeRelation> list = tourUserCommentLikeRelationService.lambdaQuery().eq(TourUserCommentLikeRelation::getUserId, TokenData.takeFromRequest().getUserId())
                .eq(TourUserCommentLikeRelation::getCommentId, commentId).list();
        if(!list.isEmpty()){
            return ResponseResult.error("500","该评论已经点赞");
        }
        byId.setLikeNum(byId.getLikeNum()+1);
        tourTravelNotesCommentService.updateById(byId);
        TourUserCommentLikeRelation tourUserCommentLikeRelation = new TourUserCommentLikeRelation();
        tourUserCommentLikeRelation.setCommentId(commentId);
        tourUserCommentLikeRelation.setUserId(TokenData.takeFromRequest().getUserId());
        tourUserCommentLikeRelationService.saveNew(tourUserCommentLikeRelation);
        return ResponseResult.success();
    }
    //对评论取消点赞
    /**
     * 对评论取消点赞。
     *
     * @param commentId 评论id。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @OperationLog(type = SysOperationLogType.ADD)
    @PostMapping("/commentLikeCancle")
    @Transactional
    public ResponseResult<Void> commentLikeCancle(@RequestBody Long commentId){
        TourTravelNotesComment byId = tourTravelNotesCommentService.getById(commentId);
        if(byId==null){
            return ResponseResult.error("500","评论不存在");
        }

        TourUserCommentLikeRelation tourUserCommentLikeRelation = new TourUserCommentLikeRelation();
        tourUserCommentLikeRelation.setCommentId(commentId);
        tourUserCommentLikeRelation.setUserId(TokenData.takeFromRequest().getUserId());
        Integer i = tourUserCommentLikeRelationService.removeBy(tourUserCommentLikeRelation);
        if(i<=0){
            return ResponseResult.success();
        }
        byId.setLikeNum(byId.getLikeNum()-1);
        tourTravelNotesCommentService.updateById(byId);
        return ResponseResult.success();
    }
    //对评论进行收藏
    /**
     * 对评论进行收藏。
     *
     * @param map 评论id。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @OperationLog(type = SysOperationLogType.ADD)
    @PostMapping("/commentCollect")
    public ResponseResult<Void> commentCollect(@RequestBody Map<String,Long> map){
        Long l = map.get("commentId");

        List<TourUserCommentCollectRelation> list = tourUserCommentCollectRelationService.lambdaQuery().eq(TourUserCommentCollectRelation::getUserId, TokenData.takeFromRequest().getUserId())
                .eq(TourUserCommentCollectRelation::getCommentId, l).list();
        if(!list.isEmpty()){
            return ResponseResult.success();
        }
        TourUserCommentCollectRelation tourUserCommentCollectRelation = new TourUserCommentCollectRelation();
        tourUserCommentCollectRelation.setCommentId(l);
        tourUserCommentCollectRelation.setUserId(TokenData.takeFromRequest().getUserId());
        tourUserCommentCollectRelationService.saveNew(tourUserCommentCollectRelation);
        return ResponseResult.success();
    }
    //对评论取消收藏
    /**
     * 对评论取消收藏。
     *
     * @param commentId 评论id。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @OperationLog(type = SysOperationLogType.ADD)
    @PostMapping("/commentCollectCancle")
    public ResponseResult<Void> commentCollectCancle(@RequestBody Long commentId){
        //获取id
        TourUserCommentCollectRelation tourUserCommentCollectRelation = new TourUserCommentCollectRelation();
        tourUserCommentCollectRelation.setCommentId(commentId);
        tourUserCommentCollectRelation.setUserId(TokenData.takeFromRequest().getUserId());
        tourUserCommentCollectRelationService.removeBy(tourUserCommentCollectRelation);
        return ResponseResult.success();
    }
    //删除评论接口
    //1.删除自己写的评论;

    /**
     * 删除自己写的评论。
     *
     * @param commentId 评论id。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @OperationLog(type = SysOperationLogType.ADD)
    @PostMapping("/myCommentDel")
    public ResponseResult<Void> myCommentDel(@RequestBody Long commentId){
        //先校验评论id是否为自己的评论
        TourTravelNotesComment tourTravelNotesComment = tourTravelNotesCommentService.getById(commentId);
        //是自己的评论，直接进行删除
        if(tourTravelNotesComment.getCommentUserId().equals(TokenData.takeFromRequest().getUserId())){
            tourTravelNotesCommentService.remove(commentId);
        }else{
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST,"不是自己的评论，无法删除");
        }
        return ResponseResult.success();
    }
    // 2.删除自己写的游记的评论
    //群聊详情接口
    //举报评论接口



    /**
     *  查询用户收藏评论
     */
    @GetMapping("/getCollectComments")
    public ResponseResult<MyPageData<CollectCommentsVo>> getCollectComments(String userId,Integer pageNum,Integer pageSize){
        if(userId==null){
            userId=TokenData.takeFromRequest().getUserId().toString();
        }
        LambdaQueryWrapper<TourUserCommentCollectRelation> query = Wrappers.<TourUserCommentCollectRelation>lambdaQuery()
                .eq(TourUserCommentCollectRelation::getUserId, userId)
                .orderByDesc(TourUserCommentCollectRelation::getCreateTime);

        List<TourUserCommentCollectRelation> list = tourUserCommentCollectRelationService.list(query);

        //自己收藏的评论ID
        Set<Long> collect = list.stream().map(TourUserCommentCollectRelation::getCommentId).collect(Collectors.toSet());
        if(collect.isEmpty()){
            return ResponseResult.success(MyPageUtil.makeResponseData(new ArrayList<>(),0L));
        }
        //开启分页
        PageMethod.startPage(pageNum==null?1:pageNum,pageSize==null?10:pageSize);
        LambdaQueryWrapper<TourTravelNotesComment> query1 = Wrappers.<TourTravelNotesComment>lambdaQuery()
                .in(TourTravelNotesComment::getId, collect)
                .orderByDesc(TourTravelNotesComment::getCreateTime);
        //分页查询评论
        List<TourTravelNotesComment> tourTravelNotesComments = tourTravelNotesCommentService.list(query1);
        long totalCount = 0L;
        if (list instanceof Page) {
            totalCount = ((Page<TourTravelNotesComment>) tourTravelNotesComments).getTotal();
        }

        List<CollectCommentsVo> result = BeanUtil.copyToList(tourTravelNotesComments, CollectCommentsVo.class);
        //发品论用户
        Set<Long> userIds = result.stream().map(item->Long.valueOf(item.getCreateUserId())).collect(Collectors.toSet());
        //评论的游记ids
        Set<Long> notice = result.stream().map(item->Long.valueOf(item.getTravelNoteId())).collect(Collectors.toSet());

        List<TourUser> inList = tourUserService.getInList(userIds);
        Map<String, TourUser> userMap = new HashMap<>();
        for (TourUser tourUser : inList) {
            userMap.put(tourUser.getUserId().toString(),tourUser);
        }
        List<TourismProjectTravelNotesWrite> inList1 = tourismProjectTravelNotesWriteService.getInList(notice);
        Map<String, TourismProjectTravelNotesWrite> noticeMap = new HashMap<>();
        //填充用户
        for (TourismProjectTravelNotesWrite tourUser : inList1) {
            noticeMap.put(tourUser.getId().toString(),tourUser);
        }
        //填充游记
        for (CollectCommentsVo c : result) {
            TourUser tourUser = userMap.get(c.getCreateUserId());
            if(tourUser!=null){
                c.setCreateName(tourUser.getShowName());
                c.setHeadImage(tourUser.getHeadImageUrl());
            }
            TourismProjectTravelNotesWrite write = noticeMap.get(c.getTravelNoteId());
            if(write!=null){
                c.setNotice(BeanUtil.toBean(write,TourismProjectTravelNotesWriteVo.class));
            }
        }

        if(CollectionUtils.isNotEmpty(result)){
            result.stream().forEach(item->{
                if(item.getNotice()!=null){
                    item.getNotice().setTourismUrlsAfterConvert(UrlConvertUtils.urlConvert(applicationConfig.getHostIpPort(), item.getNotice().getTourismUrl()));
                }
            });
        }
        return ResponseResult.success(MyPageUtil.makeResponseData(result,totalCount));
    }
}
