package com.ylx.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.common.core.domain.model.WxLoginUser;
import com.ylx.common.exception.ServiceException;
import com.ylx.common.utils.SecurityUtils;
import com.ylx.massage.domain.MaTechnician;
import com.ylx.massage.domain.vo.MaTechnicianAuditListVO;
import com.ylx.massage.service.IMaTechnicianService;
import com.ylx.merchant.domain.dto.MerchantCommentDTO;
import com.ylx.merchant.domain.vo.MerchantCommentVO;
import com.ylx.order.domain.CommentUserAudit;
import com.ylx.massage.mapper.TCommentUserAuditMapper;
import com.ylx.order.domain.TCommentPicture;
import com.ylx.order.domain.TCommentUser;
import com.ylx.order.domain.dto.MerchantMyCommentQueryDTO;
import com.ylx.order.mapper.TCommentUserMapper;
import com.ylx.order.service.TCommentUserService;
import com.ylx.order.domain.dto.OrderCommentDTO;
import com.ylx.order.domain.vo.MerchantCompositeScoreVO;
import com.ylx.order.domain.vo.MerchantMyCommentVO;
import com.ylx.order.domain.vo.TCommentUserAuditStatusCountVO;
import com.ylx.order.enums.AuditStatusEnum;
import com.ylx.order.service.TCommentPictureService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户评论表(TCommentUser)表服务实现类
 *
 * @author makejava
 * @since 2024-08-08 10:32:08
 */
@Slf4j
@Service("tCommentUserService")
public class TCommentUserServiceImpl extends ServiceImpl<TCommentUserMapper, TCommentUser> implements TCommentUserService {

    @Resource
    private TCommentUserMapper tCommentUserMapper;
    @Resource
    private TCommentUserAuditMapper tCommentUserAuditMapper;

    @Resource
    private TCommentPictureService tCommentPictureService;

    @Resource
    private IMaTechnicianService maTechnicianService;

    @Override
    public Boolean saveComment(TCommentUser comment, WxLoginUser wxLoginUser) {
        return null;
    }

    @Override
    public Page<TCommentUser> selectAll(Page<TCommentUser> page, TCommentUser tCommentUser) {
        Page<TCommentUser> pageParam = page == null ? new Page<>(1, 10) : page;
        TCommentUser query = tCommentUser == null ? new TCommentUser() : tCommentUser;
        return tCommentUserMapper.selectAll(pageParam, query);
    }

    @Override
    public TCommentUserAuditStatusCountVO selectAuditStatusCount(TCommentUser tCommentUser) {
        TCommentUser query = tCommentUser == null ? new TCommentUser() : tCommentUser;
        TCommentUserAuditStatusCountVO countVO = tCommentUserMapper.selectAuditStatusCount(query);
        return countVO == null ? buildEmptyAuditStatusCount() : countVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitComment(OrderCommentDTO dto) {
        // 1. 参数校验
        validateComment(dto);

        // 1. 获取并校验当前用户
        WxLoginUser wxLoginUser = SecurityUtils.getWxLoginUser();
        if (ObjectUtil.isNull(wxLoginUser)) {
            throw new ServiceException("用户未登录");
        }

        // 2. 构建评论实体 TCommentUser
        TCommentUser comment = new TCommentUser();
        String userId = wxLoginUser.getId();
        comment.setUserId(userId);
        comment.setNickName(wxLoginUser.getNickName());
        comment.setOrderId(dto.getOrderId());
        comment.setMerchantId(Math.toIntExact(dto.getMerchantId()));
        comment.setMerchantName(dto.getMerchantName());
        comment.setText(dto.getText());
        comment.setExperienceComment(dto.getExperienceComment());
        comment.setPriceComment(dto.getPriceComment());
        comment.setAttitudeComment(dto.getAttitudeComment());
        comment.setGroomingComment(dto.getGroomingComment());
        comment.setCommentTime(new Date());
        comment.setCreateTime(new Date());
        comment.setUpdateTime(new Date());

        // 4. 保存评论到 t_comment_user
        int insertResult = tCommentUserMapper.insert(comment);
        if (insertResult <= 0) {
            throw new RuntimeException("评论入库失败");
        }

        // 5. 构建审核记录 CommentUserAudit
        CommentUserAudit audit = new CommentUserAudit();
        audit.setCommentId(comment.getId());
        audit.setOrderId(dto.getOrderId());
        audit.setText(dto.getText());
        audit.setAuditStatus(AuditStatusEnum.PENDING.getCode());
        audit.setAuditReason(null);
        audit.setAuditorId(null);
        audit.setAuditorName(null);
        audit.setAuditTime(null);
        audit.setCreateTime(new Date());
        audit.setUpdateTime(new Date());
        audit.setIsDelete(0);
        audit.setIsPublished(0);

        int auditResult = tCommentUserAuditMapper.insert(audit);
        if (auditResult <= 0) {
            throw new ServiceException("评论审核记录入库失败");
        }
        // 5. 保存评论图片（新增）
        List<String> pictureUrls = dto.getCommentPictures();
        if (CollectionUtils.isNotEmpty(pictureUrls)) {
            tCommentPictureService.batchSavePictures(comment.getId(), pictureUrls);
        }
        log.info("评论入库成功，评论ID：{}，订单号：{}，用户ID：{}", comment.getId(), dto.getOrderId(), userId);
    }

    @Override
    public Page<MerchantCommentVO> getMerchantComment(MerchantCommentDTO dto) {

        Page<MerchantCommentVO> page = new Page<>(dto.getCurrent(), dto.getSize());
        // 1.查询评论和订单基础信息
        page = this.baseMapper.getMerchantComment(page, dto);
        if (ObjectUtil.isNotNull(page) && CollUtil.isNotEmpty(page.getRecords())) {
            List<MerchantCommentVO> records = page.getRecords();

            // 2. 提取所有评论ID
            List<String> commentIds = records.stream()
                    .map(MerchantCommentVO::getId)
                    .collect(Collectors.toList());

            // 3. 批量查询图片
            List<TCommentPicture> pictures = tCommentPictureService.selectByCommentIds(commentIds);

            // 4. 将图片分组并填充到 VO 中
            Map<String, List<String>> pictureMap = pictures.stream()
                    .collect(Collectors.groupingBy(
                            TCommentPicture::getCommentId,
                            Collectors.mapping(TCommentPicture::getPictureUrl, Collectors.toList())
                    ));

            for (MerchantCommentVO vo : records) {
                // 设置图片列表，如果没有图片则为空列表
                vo.setPictures(pictureMap.getOrDefault(vo.getId(), Collections.emptyList()));
            }
            page.setRecords(records);
            return page;
        }
        return page;
    }

    @Override
    public Page<MerchantMyCommentVO> getMerchantMyCommentPage(MerchantMyCommentQueryDTO dto) {
        Integer merchantId = getCurrentMerchantId();
        long current = dto.getCurrent();
        long size = dto.getSize();
        Page<MerchantMyCommentVO> page = new Page<>(current, size);

        Page<MerchantMyCommentVO> result = tCommentUserMapper.selectMerchantMyCommentPage(page, merchantId);
        if (ObjectUtil.isNull(result) || CollUtil.isEmpty(result.getRecords())) {
            return page;
        }

        List<MerchantMyCommentVO> records = result.getRecords();
        List<String> commentIds = records.stream()
                .map(MerchantMyCommentVO::getId)
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());

        List<TCommentPicture> pictures = tCommentPictureService.selectByCommentIds(commentIds);
        Map<String, List<String>> pictureMap = CollUtil.isEmpty(pictures)
                ? Collections.emptyMap()
                : pictures.stream()
                .filter(picture -> StrUtil.isNotBlank(picture.getCommentId()) && StrUtil.isNotBlank(picture.getPictureUrl()))
                .collect(Collectors.groupingBy(
                        TCommentPicture::getCommentId,
                        Collectors.mapping(TCommentPicture::getPictureUrl, Collectors.toList())
                ));

        for (MerchantMyCommentVO record : records) {
            record.setPictures(pictureMap.getOrDefault(record.getId(), Collections.emptyList()));
            //根据评价ID更新综合评分
            LambdaUpdateWrapper<TCommentUser> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(TCommentUser::getScore, record.getScore());
            updateWrapper.eq(TCommentUser::getId, record.getId());
            tCommentUserMapper.update(null, updateWrapper);
        }
        return result;
    }

    @Override
    public MerchantCompositeScoreVO getMerchantCompositeScore() {
        return getMerchantCompositeScoreByMerchantId(getCurrentMerchantId());
    }

    /**
     * 查询商户的综合评分
     *
     * @param merchantId
     * @return MerchantCompositeScoreVO
     */
    MerchantCompositeScoreVO getMerchantCompositeScoreByMerchantId(Integer merchantId) {
        if (ObjectUtil.isNull(merchantId) || merchantId <= 0) {
            throw new ServiceException("商户ID不能为空");
        }

        MerchantCompositeScoreVO statistic = tCommentUserMapper.selectMerchantScoreStatistics(merchantId);
        BigDecimal scoreSum = ObjectUtil.isNull(statistic) || ObjectUtil.isNull(statistic.getScoreSum())
                ? BigDecimal.ZERO
                : statistic.getScoreSum();
        Long orderCount = ObjectUtil.isNull(statistic) || ObjectUtil.isNull(statistic.getOrderCount())
                ? 0L
                : statistic.getOrderCount();

        MerchantCompositeScoreVO result = new MerchantCompositeScoreVO();
        result.setMerchantId(merchantId);
        result.setScoreSum(scoreSum);
        result.setOrderCount(orderCount);
        if (orderCount <= 0) {
            result.setComprehensiveScore(BigDecimal.ZERO.setScale(1));
            return result;
        }
        result.setComprehensiveScore(scoreSum.divide(BigDecimal.valueOf(orderCount), 1, RoundingMode.HALF_UP));
        return result;
    }

    /**
     * 校验评论参数
     */
    private void validateComment(OrderCommentDTO dto) {
        if (dto == null) {
            throw new IllegalArgumentException("评论信息不能为空");
        }
        if (ObjectUtil.isNull(dto.getOrderId())) {
            throw new IllegalArgumentException("订单ID不能为空");
        }
        if (dto.getMerchantId() == null) {
            throw new IllegalArgumentException("商户ID不能为空");
        }
        if (StrUtil.isBlank(dto.getText())) {
            throw new IllegalArgumentException("评论内容不能为空");
        }
        // 评分校验：1-5分
        checkScore(dto.getExperienceComment(), "体验评价");
        checkScore(dto.getPriceComment(), "价格评价");
        checkScore(dto.getAttitudeComment(), "态度评价");
        checkScore(dto.getGroomingComment(), "仪表仪容评价");
    }

    private void checkScore(Integer score, String fieldName) {
        if (score == null || score < 1 || score > 5) {
            throw new IllegalArgumentException(fieldName + "必须在1~5分之间");
        }
    }

    private TCommentUserAuditStatusCountVO buildEmptyAuditStatusCount() {
        TCommentUserAuditStatusCountVO countVO = new TCommentUserAuditStatusCountVO();
        countVO.setPendingCount(0L);
        countVO.setApprovedCount(0L);
        countVO.setRejectedCount(0L);
        return countVO;
    }

    /**
     * 获取当前登录商户ID
     *
     * @return Integer
     */
    private Integer getCurrentMerchantId() {
        WxLoginUser wxLoginUser = SecurityUtils.getWxLoginUser();
        if (ObjectUtil.isNull(wxLoginUser) || StrUtil.isBlank(wxLoginUser.getId())) {
            throw new ServiceException("用户未登录");
        }

        // 根据openID查询商户ID
        String openid = wxLoginUser.getCOpenid();
        LambdaQueryWrapper<MaTechnician> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaTechnician::getCOpenid, openid);
        MaTechnician technician = maTechnicianService.getOne(queryWrapper);
        if (ObjectUtil.isNull(technician)) {
            throw new ServiceException("当前登录商户不存在");
        }
        return technician.getId();
    }
}
