package shop.alien.store.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import shop.alien.entity.store.*;
import shop.alien.entity.store.excelVo.util.ExcelExporter;
import shop.alien.entity.store.vo.StoreCommentAppealLogVo;
import shop.alien.entity.store.vo.StoreCommentAppealInfoVo;
import shop.alien.entity.store.vo.StoreCommentAppealVo;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.mapper.*;
import shop.alien.store.config.WebSocketProcess;
import shop.alien.store.service.StoreCommentAppealService;
import shop.alien.store.util.FileUploadUtil;
import shop.alien.util.common.netease.TextCheckUtil;
import shop.alien.util.common.safe.TextModerationResultVO;
import shop.alien.util.common.safe.TextModerationUtil;
import shop.alien.util.common.safe.TextReviewServiceEnum;
import shop.alien.util.common.constant.CommentSourceTypeEnum;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 评论申诉表 服务实现类
 *
 * @author ssk
 * @since 2025-01-02
 */
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class StoreCommentAppealServiceImpl extends ServiceImpl<StoreCommentAppealMapper, StoreCommentAppeal> implements StoreCommentAppealService {

    private final StoreCommentAppealMapper storeCommentAppealMapper;

    private final StoreCommentMapper storeCommentMapper;

    private final StoreImgMapper storeImgMapper;

    private final StoreCommentAppealLogMapper storeCommentAppealLogMapper;

    private final FileUploadUtil fileUploadUtil;

    private final WebAuditMapper webAuditMapper;

    private final StoreDictionaryMapper storeDictionaryMapper;

    private final StoreInfoMapper storeInfoMapper;

    @Autowired
    private TextModerationUtil textModerationUtil;

    private final LifeNoticeMapper lifeNoticeMapper;

    private final StoreUserMapper storeUserMapper;

    private final WebSocketProcess webSocketProcess;

    private final CommonRatingMapper commonRatingMapper;

    private final CommonCommentMapper commonCommentMapper;

    private final LifeLikeRecordMapper lifeLikeRecordMapper;

    /**
     * 懒得查, 留着导出Excel
     */
    private List<StoreCommentAppealVo> toExcel = new ArrayList<>();

    /**
     * 申诉历史-分页
     *
     * @param pageNum      页数
     * @param pageSize     页容
     * @param storeId      门店id
     * @param appealStatus 申诉状态: 0:待处理, 1:已驳回, 2:已同意
     * @return IPage<StoreCommentAppeal>
     */
    @Override
    public IPage<StoreCommentAppealVo> getAppealHistory(Integer pageNum, Integer pageSize, Integer storeId, String appealStatus) {
        QueryWrapper<StoreCommentAppealVo> wrapper = new QueryWrapper<>();
        wrapper.eq("a.store_id", storeId)
//                .eq(!appealStatus.isEmpty() && !"null".equals(appealStatus), "a.appeal_status", appealStatus)
                .eq("a.delete_flag", 0)
                .orderByDesc("a.created_time");

        if (StringUtils.isNotEmpty(appealStatus) && !"null".equals(appealStatus)) {
            if ("0".equals(appealStatus)) {
                wrapper.in("a.appeal_status", 0, 3);
            } else {
                wrapper.eq("a.appeal_status", appealStatus);
            }
        }

        IPage<StoreCommentAppealVo> storeCommentAppealPage = storeCommentAppealMapper.getStoreCommentAppealPage(new Page<>(pageNum, pageSize), wrapper);
        storeCommentAppealPage.getRecords().forEach(item -> {
            String[] split = item.getImgId().split(",");
            List<String> imgList = new ArrayList<>();
            for (String s : split) {
                StoreImg storeImg = storeImgMapper.selectById(s);
                if (null != storeImg) {
                    imgList.add(storeImg.getImgUrl());
                }
            }
            item.setImgList(imgList);

            if (StringUtils.isNotEmpty(item.getCommentImgId())) {
                String[] imgId = item.getCommentImgId().split(",");
                List<String> commentImg = new ArrayList<>();
                for (String s : imgId) {
                    StoreImg storeImg = storeImgMapper.selectById(s);
                    if (null != storeImg) {
                        commentImg.add(storeImg.getImgUrl());
                    }
                }
                item.setCommentImgList(commentImg);
            }
        });
        return storeCommentAppealPage;
    }

    @Override
    public Map<String, Integer> getAppealHistoryCountStatus(Integer storeId) {
        Map<String, Integer> map = new HashMap<>();
        //全部
        map.put("-1", storeCommentAppealMapper.selectCount(new LambdaQueryWrapper<StoreCommentAppeal>().eq(StoreCommentAppeal::getStoreId, storeId).eq(StoreCommentAppeal::getDeleteFlag, 0)));
        //审核中
        map.put("0", storeCommentAppealMapper.selectCount(new LambdaQueryWrapper<StoreCommentAppeal>().eq(StoreCommentAppeal::getStoreId, storeId).eq(StoreCommentAppeal::getDeleteFlag, 0).eq(StoreCommentAppeal::getAppealStatus, 0)));
        //驳回
        map.put("1", storeCommentAppealMapper.selectCount(new LambdaQueryWrapper<StoreCommentAppeal>().eq(StoreCommentAppeal::getStoreId, storeId).eq(StoreCommentAppeal::getDeleteFlag, 0).eq(StoreCommentAppeal::getAppealStatus, 1)));
        // 通过
        map.put("2", storeCommentAppealMapper.selectCount(new LambdaQueryWrapper<StoreCommentAppeal>().eq(StoreCommentAppeal::getStoreId, storeId).eq(StoreCommentAppeal::getDeleteFlag, 0).eq(StoreCommentAppeal::getAppealStatus, 2)));
        return map;
    }

    /**
     * 新增申诉
     *
     * @param multipartRequest 文件
     * @param storeId          门店id
     * @param commentId        评论id
     * @param appealReason     申诉原因
     * @return Integer(0 : 申诉成功, 1 : 申诉失败, 2 : 申诉已存在, 3 : 文本内容异常)
     */
    @Override
    public Integer addAppeal(MultipartRequest multipartRequest, Integer storeId, Integer commentId, String appealReason) {
        try {
            /*Map<String, String> checkText = TextCheckUtil.check(appealReason);
            if (null == checkText || checkText.get("result").equals("1")) {
                return 3;
            }*/

            List<String> servicesList = Lists.newArrayList();
            servicesList.add(TextReviewServiceEnum.COMMENT_DETECTION_PRO.getService());
            servicesList.add(TextReviewServiceEnum.LLM_QUERY_MODERATION.getService());
            TextModerationResultVO textCheckResult = textModerationUtil.invokeFunction(appealReason, servicesList);
            if ("high".equals(textCheckResult.getRiskLevel())) {
                return 3;
            }

            List<String> fileNameSet = new ArrayList<>(multipartRequest.getMultiFileMap().keySet());
            LambdaQueryWrapper<StoreCommentAppeal> wrapper = new LambdaQueryWrapper<>();
            //待审批, 已通过
            List<Integer> list = new ArrayList<>();
            list.add(0);
            list.add(2);
            wrapper.eq(StoreCommentAppeal::getStoreId, storeId)
                    .eq(StoreCommentAppeal::getCommentId, commentId)
                    .in(StoreCommentAppeal::getAppealStatus, list)
                    .orderByDesc(StoreCommentAppeal::getCreatedTime)
                    .last("limit 1");
            /*if (this.getOne(wrapper) != null) {
                return 2;
            }*/
            StoreCommentAppeal storeCommentAppeal = new StoreCommentAppeal();
            StringBuilder imgId = new StringBuilder();
            for (int i = 0; i < fileNameSet.size(); i++) {
                MultipartFile multipartFile = multipartRequest.getFileMap().get(fileNameSet.get(i));
                if (null != multipartFile) {
                    StoreImg storeImg = new StoreImg();
                    storeImg.setStoreId(storeId);
                    storeImg.setImgType(9);
                    storeImg.setImgSort(i + 1);
                    storeImg.setImgUrl(fileUploadUtil.uploadOneFile(multipartFile));
                    storeImgMapper.insert(storeImg);
                    imgId.append(storeImg.getId()).append(",");
                }
            }
            if (!imgId.toString().isEmpty()) {
                storeCommentAppeal.setImgId(imgId.substring(0, imgId.length() - 1));
            }
            storeCommentAppeal.setStoreId(storeId);
            storeCommentAppeal.setCommentId(commentId);
            storeCommentAppeal.setAppealReason(appealReason);
            storeCommentAppeal.setAppealStatus(0);
            boolean storeCommentAppealSave = this.save(storeCommentAppeal);
            //商家申诉
            StoreCommentAppealLog storeCommentAppealLog = new StoreCommentAppealLog();
            storeCommentAppealLog.setAppealId(storeCommentAppeal.getId());
            storeCommentAppealLog.setProcessType(0);
            storeCommentAppealLog.setDeleteFlag(0);
            storeCommentAppealLog.setCreatedTime(storeCommentAppeal.getCreatedTime());
            boolean result = storeCommentAppealSave && storeCommentAppealLogMapper.insert(storeCommentAppealLog) > 0;
            //系统审核
            StoreCommentAppealLog storeCommentAppealLogSystem = new StoreCommentAppealLog();
            storeCommentAppealLogSystem.setAppealId(storeCommentAppeal.getId());
            storeCommentAppealLogSystem.setProcessType(1);
            storeCommentAppealLogSystem.setDeleteFlag(0);
            storeCommentAppealLogSystem.setCreatedTime(storeCommentAppeal.getCreatedTime());
            boolean resultSystem = storeCommentAppealSave && storeCommentAppealLogMapper.insert(storeCommentAppealLogSystem) > 0;
            return result && resultSystem ? 0 : 1;
        } catch (Exception e) {
            return 1;
        }
    }

    /**
     * 新增申诉
     *
     * @param multipartRequest 文件
     * @param storeId          门店id
     * @param commentId        评论id
     * @param appealReason     申诉原因
     * @return Integer(0 : 申诉成功, 1 : 申诉失败, 2 : 申诉已存在, 3 : 文本内容异常)
     */
    @Override
    public StoreCommentAppealInfoVo addAppealNew(MultipartRequest multipartRequest, Integer storeId, Integer commentId, String appealReason) {
        StoreCommentAppealInfoVo storeCommentAppealInfoVo = new StoreCommentAppealInfoVo();
        try {
            Map<String, String> checkText = TextCheckUtil.check(appealReason);
            // todo 暂时去掉校验，防止校验不通过
//            if (null == checkText || checkText.get("result").equals("1")) {
//                storeCommentAppealInfoVo.setResult(3);
//                return storeCommentAppealInfoVo;
//            }

            List<String> servicesList = Lists.newArrayList();
            servicesList.add(TextReviewServiceEnum.COMMENT_DETECTION_PRO.getService());
            servicesList.add(TextReviewServiceEnum.LLM_QUERY_MODERATION.getService());
            TextModerationResultVO textCheckResult = textModerationUtil.invokeFunction(appealReason, servicesList);
            if ("high".equals(textCheckResult.getRiskLevel())) {
                storeCommentAppealInfoVo.setResult(3);
                return storeCommentAppealInfoVo;
            }

            List<String> fileNameSet = new ArrayList<>(multipartRequest.getMultiFileMap().keySet());
            LambdaQueryWrapper<StoreCommentAppeal> wrapper = new LambdaQueryWrapper<>();
            //待审批, 已通过
            List<Integer> list = new ArrayList<>();
            list.add(0);
            list.add(2);
            wrapper.eq(StoreCommentAppeal::getStoreId, storeId)
                    .eq(StoreCommentAppeal::getCommentId, commentId)
                    .in(StoreCommentAppeal::getAppealStatus, list)
                    .orderByDesc(StoreCommentAppeal::getCreatedTime)
                    .last("limit 1");
            if (this.getOne(wrapper) != null) {
                storeCommentAppealInfoVo.setResult(2);
                return storeCommentAppealInfoVo;
            }
            /*if (this.getOne(wrapper) != null) {
                return 2;
            }*/
            StoreCommentAppeal storeCommentAppeal = new StoreCommentAppeal();
            StringBuilder imgId = new StringBuilder();
            for (int i = 0; i < fileNameSet.size(); i++) {
                MultipartFile multipartFile = multipartRequest.getFileMap().get(fileNameSet.get(i));
                if (null != multipartFile) {
                    StoreImg storeImg = new StoreImg();
                    storeImg.setStoreId(storeId);
                    storeImg.setImgType(9);
                    storeImg.setImgSort(i + 1);
                    storeImg.setImgUrl(fileUploadUtil.uploadOneFile(multipartFile));
                    storeImgMapper.insert(storeImg);
                    imgId.append(storeImg.getId()).append(",");
                }
            }
            if (!imgId.toString().isEmpty()) {
                storeCommentAppeal.setImgId(imgId.substring(0, imgId.length() - 1));
            }
            storeCommentAppeal.setStoreId(storeId);
            storeCommentAppeal.setCommentId(commentId);
            storeCommentAppeal.setAppealReason(appealReason);
            storeCommentAppeal.setAppealStatus(0);

            int insertResult = storeCommentAppealMapper.insert(storeCommentAppeal);
            boolean storeCommentAppealSave = insertResult > 0;

            BeanUtils.copyProperties(storeCommentAppeal, storeCommentAppealInfoVo);
            //商家申诉
            StoreCommentAppealLog storeCommentAppealLog = new StoreCommentAppealLog();
            storeCommentAppealLog.setAppealId(storeCommentAppeal.getId());
            storeCommentAppealLog.setProcessType(0);
            storeCommentAppealLog.setDeleteFlag(0);
            storeCommentAppealLog.setCreatedTime(storeCommentAppeal.getCreatedTime());
            boolean result = storeCommentAppealSave && storeCommentAppealLogMapper.insert(storeCommentAppealLog) > 0;
            //系统审核
            StoreCommentAppealLog storeCommentAppealLogSystem = new StoreCommentAppealLog();
            storeCommentAppealLogSystem.setAppealId(storeCommentAppeal.getId());
            storeCommentAppealLogSystem.setProcessType(1);
            storeCommentAppealLogSystem.setDeleteFlag(0);
            storeCommentAppealLogSystem.setCreatedTime(storeCommentAppeal.getCreatedTime());
            boolean resultSystem = storeCommentAppealSave && storeCommentAppealLogMapper.insert(storeCommentAppealLogSystem) > 0;
            storeCommentAppealInfoVo.setResult(result && resultSystem ? 0 : 1);
        } catch (Exception e) {
            storeCommentAppealInfoVo.setResult(1);
            return storeCommentAppealInfoVo;
        }
        return storeCommentAppealInfoVo;
    }

    /**
     * 申诉详情
     *
     * @param id 申诉id
     * @return StoreCommentAppealVo
     */
    @Override
    public StoreCommentAppealVo getStoreCommentAppealDetail(Integer id) {
        QueryWrapper<StoreCommentAppealVo> storeCommentAppealVoQueryWrapper = new QueryWrapper<>();
        storeCommentAppealVoQueryWrapper.eq("a.id", id);
        StoreCommentAppealVo commentDetail = storeCommentAppealMapper.getCommentDetail(storeCommentAppealVoQueryWrapper);

        String[] split = commentDetail.getImgId().split(",");
        List<String> imgList = new ArrayList<>();
        for (String s : split) {
            StoreImg storeImg = storeImgMapper.selectById(s);
            if (null != storeImg) {
                imgList.add(storeImg.getImgUrl());
            }
        }
        commentDetail.setImgList(imgList);

        // 处理评价图片（common_rating.image_urls 已经是URL字符串，不是ID）
        if (StringUtils.isNotEmpty(commentDetail.getCommentImgId())) {
            String[] split2 = commentDetail.getCommentImgId().split(",");
            List<String> imgList2 = new ArrayList<>();
            for (String s : split2) {
                String trimmedUrl = s.trim();
                if (StringUtils.isNotEmpty(trimmedUrl)) {
                    // 如果已经是URL格式（包含http://或https://），直接使用
                    if (trimmedUrl.startsWith("http://") || trimmedUrl.startsWith("https://")) {
                        imgList2.add(trimmedUrl);
                    } else {
                        // 否则尝试作为ID查询（兼容旧数据）
                        StoreImg storeImg = storeImgMapper.selectById(trimmedUrl);
                        if (null != storeImg) {
                            imgList2.add(storeImg.getImgUrl());
                        }
                    }
                }
            }
            commentDetail.setCommentImgList(imgList2);
        } else {
            commentDetail.setCommentImgList(new ArrayList<>());
        }

        List<StoreCommentAppealLogVo> storeCommentAppealLogVo = storeCommentAppealLogMapper.getStoreCommentAppealLogVo(commentDetail.getId());
        commentDetail.setStoreCommentAppealLogList(storeCommentAppealLogVo);
        if (ObjectUtils.isNotEmpty(storeCommentAppealLogVo)) {
            commentDetail.setLogRemark(storeCommentAppealLogVo.get(storeCommentAppealLogVo.size() - 1).getLogRemark());
        }
        return commentDetail;
    }

    /**
     * web-申诉分页查询
     *
     * @param pageNum      页数
     * @param pageSize     页容
     * @param storeName    门店名称
     * @param storeContact 门店联系人
     * @param storePhone   门店电话
     * @param appealStatus 申诉状态: 0:待处理, 1:已驳回, 2:已同意
     * @return IPage<StoreCommentAppealVo>
     */
    @Override
    public IPage<StoreCommentAppealVo> getStoreAppealPage(Integer pageNum, Integer pageSize, String storeName, String storeContact, String storePhone, String appealStatus) {
        IPage<StoreCommentAppealVo> storePage = new Page<>(pageNum, pageSize);
        QueryWrapper<StoreCommentAppealVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(!storeName.isEmpty(), "e.store_name", storeName);
        queryWrapper.like(!storeContact.isEmpty(), "f.name", storeContact);
        queryWrapper.like(!storePhone.isEmpty(), "f.phone", storePhone);
        queryWrapper.like(!appealStatus.isEmpty(), "a.appeal_status", appealStatus);
        queryWrapper.orderByDesc("a.created_time");
        IPage<StoreCommentAppealVo> storeCommentAppealPage = storeCommentAppealMapper.getStoreCommentAppealPage(storePage, queryWrapper);
        List<StoreCommentAppealVo> records = storeCommentAppealPage.getRecords();
        if (!records.isEmpty()) {
            // 提前查询所有需要的字典数据
            Set<String> allTypes = records.stream()
                    .map(StoreCommentAppealVo::getStoreType)
                    .flatMap(type -> Arrays.stream(type.split(",")))
                    .collect(Collectors.toSet());
            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .eq(StoreDictionary::getTypeName, "storeType")
                            .in(StoreDictionary::getDictId, allTypes)
            );
            Map<String, String> typeMap = storeDictionaries.stream()
                    .collect(Collectors.toMap(
                            StoreDictionary::getDictId,
                            StoreDictionary::getDictDetail
                    ));
            storeCommentAppealPage.getRecords().forEach(item -> {
                String[] types = item.getStoreType().split(",");
                List<String> typeDetails = Arrays.stream(types)
                        .map(typeMap::get)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                item.setStoreTypeStr(String.join(",", typeDetails));
                String[] split = item.getImgId().split(",");
                List<String> imgList = new ArrayList<>();
                for (String s : split) {
                    StoreImg storeImg = storeImgMapper.selectById(s);
                    if (null != storeImg) {
                        imgList.add(storeImg.getImgUrl());
                    }
                }
                item.setImgList(imgList);
            });
        }
        toExcel = storeCommentAppealPage.getRecords();
        return storeCommentAppealPage;
    }

    /**
     * 修改申诉状态
     *
     * @param id           申诉id
     * @param appealStatus 申诉状态: 0:待处理, 1:已驳回, 2:已同意
     * @return boolean
     */
    @Override
    public boolean setAppealStatus(Integer id, Integer appealStatus, String logRemark) {
        StoreCommentAppeal sca = storeCommentAppealMapper.selectById(id);
        if (sca == null){
            return false;
        }
        Integer storeId = sca.getStoreId();
        StoreCommentAppeal storeCommentAppeal = new StoreCommentAppeal();
        storeCommentAppeal.setId(id);
        storeCommentAppeal.setAppealStatus(appealStatus);
        switch (appealStatus) {
            case 0:
                storeCommentAppeal.setFinalResult("待处理");
                break;
            case 1:
                storeCommentAppeal.setFinalResult("已驳回");
                break;
            case 2:
                storeCommentAppeal.setFinalResult("已同意");
                // 审核通过后删除评价（common_rating）和评论（common_comment）
                StoreCommentAppeal byId = this.getById(id);
                Integer ratingId = byId.getCommentId(); // commentId 实际存储的是评价ID（common_rating.id）
                
                if (ratingId != null) {
                    // 1. 删除评价（逻辑删除 common_rating 表）
                    // 注意：因为 deleteFlag 字段有 @TableLogic 注解，必须使用原生 SQL 绕过限制
                    CommonRating rating = commonRatingMapper.selectById(ratingId);
                    if (rating != null) {
                        // 使用原生 SQL 方法直接更新 delete_flag
                        int rows = commonRatingMapper.logicDeleteById(ratingId);
                        log.info("删除评价结果，ratingId={}，影响行数={}", ratingId, rows);
                    }
                    
                    // 2. 查询该评价下的所有评论ID（用于后续删除点赞记录）
                    LambdaQueryWrapper<CommonComment> commentQueryWrapper = new LambdaQueryWrapper<>();
                    commentQueryWrapper.eq(CommonComment::getSourceType, CommentSourceTypeEnum.STORE_COMMENT.getType())
                                      .eq(CommonComment::getSourceId, ratingId)
                                      .eq(CommonComment::getDeleteFlag, 0);
                    List<CommonComment> comments = commonCommentMapper.selectList(commentQueryWrapper);
                    List<Long> commentIds = comments.stream().map(CommonComment::getId).collect(Collectors.toList());
                    
                    // 3. 删除该评价下的所有评论（使用原生 SQL 绕过 @TableLogic 限制）
                    int commentRows = commonCommentMapper.logicDeleteBySourceId(
                            CommentSourceTypeEnum.STORE_COMMENT.getType(), ratingId);
                    log.info("删除评价下的评论结果，ratingId={}，影响行数={}", ratingId, commentRows);
                    
                    // 4. 删除评价的点赞记录（type=7 表示评价点赞）
                    LambdaUpdateWrapper<LifeLikeRecord> ratingLikeWrapper = new LambdaUpdateWrapper<>();
                    ratingLikeWrapper.eq(LifeLikeRecord::getType, "7")
                                    .eq(LifeLikeRecord::getHuifuId, String.valueOf(ratingId))
                                    .eq(LifeLikeRecord::getDeleteFlag, 0);
                    ratingLikeWrapper.set(LifeLikeRecord::getDeleteFlag, 1);
                    ratingLikeWrapper.set(LifeLikeRecord::getUpdatedTime, new Date());
                    lifeLikeRecordMapper.update(null, ratingLikeWrapper);
                    log.info("删除评价的点赞记录，ratingId={}", ratingId);
                    
                    // 5. 删除评论的点赞记录（type=1 表示评论点赞）
                    if (!commentIds.isEmpty()) {
                        for (Long commentId : commentIds) {
                            LambdaUpdateWrapper<LifeLikeRecord> commentLikeWrapper = new LambdaUpdateWrapper<>();
                            commentLikeWrapper.eq(LifeLikeRecord::getType, "1")
                                             .eq(LifeLikeRecord::getHuifuId, String.valueOf(commentId))
                                             .eq(LifeLikeRecord::getDeleteFlag, 0);
                            commentLikeWrapper.set(LifeLikeRecord::getDeleteFlag, 1);
                            commentLikeWrapper.set(LifeLikeRecord::getUpdatedTime, new Date());
                            lifeLikeRecordMapper.update(null, commentLikeWrapper);
                        }
                        log.info("删除评论的点赞记录，评论数={}", commentIds.size());
                    }
                    
                    // 6. 重新统计店铺评分（删除评价后需要更新门店评分）
                    if (rating != null && rating.getBusinessType() == 1) {
                        updateStoreScore(rating.getBusinessId());
                    }
                }
                
                // 7. 不删除申诉记录，保留以便申诉历史能显示已通过的记录
                // 申诉记录保留，只更新状态为"已同意"，评价快照数据仍可在申诉历史中查看
                log.info("申诉审核通过，保留申诉记录，申诉ID={}，评价ID={}", id, ratingId);
                break;
        }
        //商家申诉
        //处理中台审核记录
        LambdaUpdateWrapper<WebAudit> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(WebAudit::getStoreCommentAppealId, storeCommentAppeal.getId());
        wrapper.set(WebAudit::getStatus, "1");
        webAuditMapper.update(null, wrapper);

        StoreCommentAppealLog storeCommentAppealLog = new StoreCommentAppealLog();
        storeCommentAppealLog.setAppealId(storeCommentAppeal.getId());
        if (appealStatus == 1) {
            storeCommentAppealLog.setProcessType(4);
        } else if (appealStatus == 2) {
            storeCommentAppealLog.setProcessType(5);
        }
        storeCommentAppealLog.setDeleteFlag(0);
        storeCommentAppealLog.setCreatedTime(new Date());
        storeCommentAppealLog.setLogRemark(logRemark);
        storeCommentAppealLogMapper.insert(storeCommentAppealLog);
        boolean result = this.updateById(storeCommentAppeal);

        // 发送通知
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String commonDate = simpleDateFormat.format(new Date());
        String text = "";
        if(appealStatus==2) {
            text = "您在"+commonDate+"提交了申诉删除差评，经核实，确为不实评价，申诉成功，已将此条评价删除。";
        } else if(appealStatus==1){
            text = "您在"+commonDate+"提交了申诉删除差评，经核实，确为顾客真实感受，申诉失败，此条评价不会被删除。";
        }
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if(StringUtils.isEmpty(text) || storeInfo == null || StringUtils.isEmpty(storeInfo.getStoreTel())) {
            return result;
        }
        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfo.getId()).eq(StoreUser::getDeleteFlag, 0));

        LifeNotice lifeMessage = new LifeNotice();
        lifeMessage.setReceiverId("store_" + storeUser.getPhone());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", text);
        lifeMessage.setContext(jsonObject.toJSONString());
        lifeMessage.setTitle("申诉删除差评");
        lifeMessage.setSenderId("system");
        lifeMessage.setIsRead(0);
        lifeMessage.setNoticeType(1);
        lifeNoticeMapper.insert(lifeMessage);

        WebSocketVo websocketVo = new WebSocketVo();
        websocketVo.setSenderId("system");
        websocketVo.setReceiverId("store_" + storeUser.getPhone());
        websocketVo.setCategory("notice");
        websocketVo.setNoticeType("1");
        websocketVo.setIsRead(0);
        websocketVo.setText(JSONObject.from(lifeMessage).toJSONString());
        try {
            webSocketProcess.sendMessage("store_" + storeUser.getPhone(), JSONObject.from(websocketVo).toJSONString());
        } catch (Exception e) {
            log.error("StoreCommentAppealServiceImpl webSocketProcess Stack={}", e);
        }

        return result;
    }

    /**
     * 导出Excel
     *
     * @return ResponseEntity
     */
    @Override
    public ResponseEntity<byte[]> exportToExcel() {
        try {
            String[] headers = {"商家名称", "联系人", "联系电话", "经营种类", "申诉时间", "顾客评论", "申诉理由", "状态"};
            byte[] excelData = ExcelExporter.exportToExcel(toExcel, headers, "申诉管理列表");
            HttpHeaders responseHeaders = new HttpHeaders();
            responseHeaders.add("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode("申诉管理列表.xlsx") + "\";charset=utf-8");
            responseHeaders.set("charset", "UTF-8");
            return new ResponseEntity<>(excelData, responseHeaders, HttpStatus.OK);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 更新店铺评分（删除评价后重新计算门店评分）
     *
     * @param businessId 店铺ID
     */
    private void updateStoreScore(Integer businessId) {
        try {
            // 查询该店铺的所有有效评价
            LambdaQueryWrapper<CommonRating> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CommonRating::getBusinessType, 1)
                   .eq(CommonRating::getBusinessId, businessId)
                   .eq(CommonRating::getDeleteFlag, 0)
                   .eq(CommonRating::getIsShow, 1)
                   .eq(CommonRating::getAuditStatus, 1);
            List<CommonRating> ratings = commonRatingMapper.selectList(wrapper);
            
            int total = ratings.size();
            if (total == 0) {
                // 没有评价，设置默认评分为0
                StoreInfo storeInfo = new StoreInfo();
                storeInfo.setId(businessId);
                storeInfo.setScoreAvg(0.0);
                storeInfo.setScoreOne(0.0);
                storeInfo.setScoreTwo(0.0);
                storeInfo.setScoreThree(0.0);
                storeInfoMapper.updateById(storeInfo);
                log.info("店铺无有效评价，重置评分为0，businessId={}", businessId);
                return;
            }
            
            // 计算平均评分
            double scoreSum = ratings.stream().mapToDouble(r -> r.getScore() != null ? r.getScore() : 0.0).sum();
            double scoreOneSum = ratings.stream().mapToDouble(r -> r.getScoreOne() != null ? r.getScoreOne() : 0.0).sum();
            double scoreTwoSum = ratings.stream().mapToDouble(r -> r.getScoreTwo() != null ? r.getScoreTwo() : 0.0).sum();
            double scoreThreeSum = ratings.stream().mapToDouble(r -> r.getScoreThree() != null ? r.getScoreThree() : 0.0).sum();
            
            double scoreAvg = Math.round((scoreSum / total) * 100.0) / 100.0;
            double scoreOne = Math.round((scoreOneSum / total) * 100.0) / 100.0;
            double scoreTwo = Math.round((scoreTwoSum / total) * 100.0) / 100.0;
            double scoreThree = Math.round((scoreThreeSum / total) * 100.0) / 100.0;
            
            StoreInfo storeInfo = new StoreInfo();
            storeInfo.setId(businessId);
            storeInfo.setScoreAvg(scoreAvg);
            storeInfo.setScoreOne(scoreOne);
            storeInfo.setScoreTwo(scoreTwo);
            storeInfo.setScoreThree(scoreThree);
            storeInfoMapper.updateById(storeInfo);
            
            log.info("更新店铺评分成功，businessId={}，评价数={}，scoreAvg={}", businessId, total, scoreAvg);
        } catch (Exception e) {
            log.error("更新店铺评分失败，businessId={}，error={}", businessId, e.getMessage());
        }
    }
}
