package shop.alien.store.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import shop.alien.entity.result.R;
import shop.alien.entity.store.*;
import shop.alien.entity.store.vo.CommentAppealVo;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.mapper.*;
import shop.alien.store.config.WebSocketProcess;
import shop.alien.store.service.CommentAppealService;
import shop.alien.store.service.OrderReviewService;
import shop.alien.store.service.ReviewCommentService;
import shop.alien.util.common.JwtUtil;
import shop.alien.util.common.ListToPage;
import shop.alien.util.type.LifeNoticeUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 评论申诉表 服务实现类
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Transactional
@Service
@RequiredArgsConstructor
public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, CommentAppeal> implements CommentAppealService {
    private final OrderReviewService orderReviewService;
    private final ReviewCommentService reviewCommentService;
    private final WebSocketProcess webSocketProcess;
    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeNoticeUtil lifeNoticeUtil;
    private final OrderReviewMapper orderReviewMapper;
    private final LifeUserMapper lifeUserMapper;
    private final LawyerUserMapper lawyerUserMapper;
    private final LawyerConsultationOrderMapper lawyerConsultationOrderMapper;


    @Override
    public R<CommentAppeal> submitAppeal(CommentAppeal commentAppeal) {
        log.info("CommentAppealServiceImpl.submitAppeal?commentAppeal={}", commentAppeal);

        // 校验必填字段
        if (commentAppeal.getCommentId() == null) {
            return R.fail("评论ID不能为空");
        }
        if (!StringUtils.hasText(commentAppeal.getAppealReason())) {
            return R.fail("申诉理由不能为空");
        }

        // 检查该评论是否已有待处理或已通过的申诉
        LambdaQueryWrapper<CommentAppeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CommentAppeal::getCommentId, commentAppeal.getCommentId());
        wrapper.eq(CommentAppeal::getDeleteFlag, 0);
        wrapper.in(CommentAppeal::getStatus, 0, 1); // 待处理或已通过
        CommentAppeal existingAppeal = this.getOne(wrapper);
        if (existingAppeal != null) {
            return R.fail("该评论已有申诉记录，无法重复申诉");
        }

        OrderReview orderReview = orderReviewMapper.selectById(commentAppeal.getCommentId());
        if(orderReview != null){
            if (orderReview.getOrderId() != null) {
                commentAppeal.setOrderId(orderReview.getOrderId());
            }
        }

        // 设置默认值
        commentAppeal.setStatus(0); // 待处理
        if (commentAppeal.getDeleteFlag() == null) {
            commentAppeal.setDeleteFlag(0);
        }

        // 保存申诉
        boolean result = this.save(commentAppeal);
        if (result) {
            log.info("提交申诉成功，id={}", commentAppeal.getId());

            if(orderReview != null){
                orderReview.setAppealId(commentAppeal.getId().toString());
                orderReviewMapper.updateById(orderReview);
            }

            // 更新订单表的申诉状态为2（申诉中）
            if (commentAppeal.getOrderId() != null) {
                LambdaUpdateWrapper<LawyerConsultationOrder> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                lambdaUpdateWrapper.eq(LawyerConsultationOrder::getId, commentAppeal.getOrderId())
                        .set(LawyerConsultationOrder::getIsAppealed, 2);
                lawyerConsultationOrderMapper.update(null, lambdaUpdateWrapper);
                log.info("更新订单申诉状态成功，orderId={}, isAppealed=2", commentAppeal.getOrderId());
            }

            // 发送通知给评价用户，告知其评价被申诉了
            sendSubmitAppealNotification(commentAppeal);

            return R.data(commentAppeal, "申诉提交成功");
        } else {
            return R.fail("申诉提交失败");
        }
    }

    @Override
    public R<Boolean> auditAppeal(Integer id, Integer status, String reviewReasons) {
        log.info("CommentAppealServiceImpl.auditAppeal?id={}, status={}, reviewReasons={}", id, status, reviewReasons);

        // 校验参数
        if (id == null) {
            return R.fail("申诉ID不能为空");
        }

        if (status == null || (status != 1 && status != 2)) {
            return R.fail("审核状态不正确，必须是1(已通过)或2(已驳回)");
        }

        // 从 token 获取当前登录用户ID（审核人）
        Integer auditUserId = null;
        try {
            com.alibaba.fastjson.JSONObject userInfo = JwtUtil.getCurrentUserInfo();
            if (userInfo != null && userInfo.getString("userId") != null) {
                auditUserId = userInfo.getInteger("userId");
            }
        } catch (Exception e) {
            log.warn("获取当前用户信息失败，将使用默认值", e);
        }

        // 查询申诉记录
        CommentAppeal appeal = this.getById(id);
        if (appeal == null || appeal.getDeleteFlag() == 1) {
            return R.fail("申诉记录不存在或已被删除");
        }

        // 检查状态
        if (appeal.getStatus() != 0) {
            return R.fail("该申诉已处理，无法重复审核");
        }

        // 查询评价信息
        OrderReview orderReview = orderReviewMapper.selectById(appeal.getCommentId());
        if (orderReview == null) {
            return R.fail("评价记录不存在");
        }

        // 更新状态
        CommentAppeal updateAppeal = new CommentAppeal();
        updateAppeal.setId(id);
        updateAppeal.setStatus(status);
        updateAppeal.setAppealReviewTime(new Date());
        if (auditUserId != null) {
            updateAppeal.setUpdatedUserId(auditUserId);
        }
        // 设置审核原因
        if (StringUtils.hasText(reviewReasons)) {
            updateAppeal.setReviewReasons(reviewReasons);
        }

        boolean result = this.updateById(updateAppeal);
        if (result) {
            String statusText = status == 1 ? "已通过" : "已驳回";
            log.info("审核申诉成功，id={}, status={}, auditUserId={}", id, statusText, auditUserId);

            // 如果申诉通过，删除评价及该评价下的所有评论和回复
            if (status == 1) {
//                deleteReviewAndRelatedData(appeal.getCommentId());
                orderReviewService.deleteReviewByAdmin(appeal.getCommentId());
            }

            // 发送通知
            sendAuditNotification(appeal, orderReview, status, reviewReasons);

            return R.success("申诉" + statusText);
        } else {
            return R.fail("审核失败");
        }
    }

    /**
     * 发送提交申诉通知（给评价用户）
     *
     * @param appeal 申诉记录
     */
    private void sendSubmitAppealNotification(CommentAppeal appeal) {
        try {
            // 查询律师用户信息
            LambdaQueryWrapper<LawyerUser> lawyerUser = new LambdaQueryWrapper<>();
            lawyerUser.eq(LawyerUser::getId, appeal.getLawyerUserId());
            LawyerUser lifeUser = lawyerUserMapper.selectOne(lawyerUser);
            if (lifeUser == null) {
                log.warn("律师用户不存在，lawyerUserId={}", appeal.getLawyerUserId());
                return;
            }
            LambdaQueryWrapper<OrderReview> orderReviewLambdaQueryWrapper = new LambdaQueryWrapper<>();
            orderReviewLambdaQueryWrapper.eq(OrderReview::getId, appeal.getCommentId());
            OrderReview orderReview = orderReviewMapper.selectOne(orderReviewLambdaQueryWrapper);
            String orderNumber = "";
            if (orderReview != null) {
                orderNumber = orderReview.getOrderNumber();
            }
            String receiverId = "user_" + lifeUser.getPhone();
            String message = String.format("您提交的差评申诉信息，订单编号为" + orderNumber + "，已提交至平台审核，1-3个工作日会发送您审核结果，请注意查收。");

            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setReceiverId(receiverId);
            lifeNotice.setBusinessId(appeal.getId());
            lifeNotice.setTitle("申诉通知");
            lifeNotice.setSenderId("system");
            lifeNotice.setIsRead(0);
            lifeNotice.setNoticeType(1);
            lifeNotice.setDeleteFlag(0);

            com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
            jsonObject.put("message", message);
//            jsonObject.put("orderNumber", orderReview.getOrderNumber());
//            jsonObject.put("appealId", appeal.getId());
//            jsonObject.put("status", "pending"); // 待审核状态
            lifeNotice.setContext(jsonObject.toJSONString());

            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            lifeNoticeMapper.insert(lifeNotice);

            // 发送 WebSocket 消息
            sendWebSocketNotification(receiverId, lifeNotice);
            log.info("提交申诉通知发送成功，receiverId={}, appealId={}", receiverId, appeal.getId());
        } catch (Exception e) {
            log.error("发送提交申诉通知失败，appealId={}, error={}", appeal.getId(), e.getMessage(), e);
        }
    }

    /**
     * 发送审核通知
     *
     * @param appeal      申诉记录
     * @param orderReview 评价记录
     * @param status      审核状态 1:已通过, 2:已驳回
     */
    private void sendAuditNotification(CommentAppeal appeal, OrderReview orderReview, Integer status, String reviewReasons) {
        try {
            if (status == 1) {
                // 审核通过：给评价用户发通知（评价被删除）
                sendNotificationToReviewUser(orderReview, appeal);
                // 审核通过：给律师发通知（申诉成功）
                sendNotificationToLawyer(orderReview, appeal, true, null);
            } else {
                // 审核驳回：给律师发通知（申诉失败）
                sendNotificationToLawyer(orderReview, appeal, false, reviewReasons);
            }
        } catch (Exception e) {
            log.error("发送审核通知失败，appealId={}, status={}, error={}", appeal.getId(), status, e.getMessage(), e);
        }
    }

    /**
     * 给评价用户发送通知（评价被删除）
     *
     * @param orderReview 评价记录
     * @param appeal      申诉记录
     */
    private void sendNotificationToReviewUser(OrderReview orderReview, CommentAppeal appeal) {
        try {
            LifeUser lifeUser = lifeUserMapper.selectById(orderReview.getUserId());
            if (lifeUser == null) {
                log.warn("评价用户不存在，userId={}", orderReview.getUserId());
                return;
            }

            String receiverId = "user_" + lifeUser.getUserPhone();
            String message = String.format("您对订单编号为" + orderReview.getOrderNumber() + "的评价，律师已进行申诉，经核实，您的评价不实，平台已删除此条评价及回复。");

            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setReceiverId(receiverId);
            lifeNotice.setBusinessId(appeal.getId());
            lifeNotice.setTitle("评价被申诉成功通知");
            lifeNotice.setSenderId("system");
            lifeNotice.setIsRead(0);
            lifeNotice.setNoticeType(1);
            lifeNotice.setDeleteFlag(0);

            com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
            jsonObject.put("message", message);
            lifeNotice.setContext(jsonObject.toJSONString());

            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            lifeNoticeMapper.insert(lifeNotice);

            // 发送 WebSocket 消息
            sendWebSocketNotification(receiverId, lifeNotice);
            log.info("评价用户通知发送成功，receiverId={}", receiverId);
        } catch (Exception e) {
            log.error("给评价用户发送通知失败，userId={}, error={}", orderReview.getUserId(), e.getMessage(), e);
        }
    }

    /**
     * 给律师发送通知（申诉成功/失败）
     *
     * @param orderReview 评价记录
     * @param appeal      申诉记录
     * @param isSuccess   是否成功
     */
    private void sendNotificationToLawyer(OrderReview orderReview, CommentAppeal appeal, boolean isSuccess, String reviewReasons) {
        try {
            LawyerUser lawyerUser = lawyerUserMapper.selectById(orderReview.getLawyerUserId());
            if (lawyerUser == null) {
                log.warn("律师用户不存在，lawyerUserId={}", orderReview.getLawyerUserId());
                return;
            }

            // 律师的接收ID格式可能是 "lawyer_" + phone 或其他格式，需要根据实际情况调整
            String receiverId = "lawyer_" + lawyerUser.getPhone();
            String title = isSuccess ? "申诉成功通知" : "申诉失败通知";
            String message = isSuccess
                    ? String.format("您的编号" + orderReview.getOrderNumber() + "的订单，提交的差评申诉信息，经核实，评价内容不实，平台已删除此条评价。")
                    : String.format("您的编号" + orderReview.getOrderNumber() + "的订单，提交的差评申诉信息，经核实，评价内容属实。失败原因：" + reviewReasons + "。");

            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setReceiverId(receiverId);
            lifeNotice.setBusinessId(appeal.getId());
            lifeNotice.setTitle(title);
            lifeNotice.setSenderId("system");
            lifeNotice.setIsRead(0);
            lifeNotice.setNoticeType(1);
            lifeNotice.setDeleteFlag(0);

            com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
            jsonObject.put("message", message);
            lifeNotice.setContext(jsonObject.toJSONString());

            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            lifeNoticeMapper.insert(lifeNotice);

            // 发送 WebSocket 消息
            sendWebSocketNotification(receiverId, lifeNotice);
            log.info("律师通知发送成功，receiverId={}, isSuccess={}", receiverId, isSuccess);
        } catch (Exception e) {
            log.error("给律师发送通知失败，lawyerUserId={}, error={}", orderReview.getLawyerUserId(), e.getMessage(), e);
        }
    }

    /**
     * 发送 WebSocket 通知
     *
     * @param receiverId 接收人ID
     * @param lifeNotice 通知内容
     */
    private void sendWebSocketNotification(String receiverId, LifeNotice lifeNotice) {
        try {
            WebSocketVo webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId("system");
            webSocketVo.setReceiverId(receiverId);
            webSocketVo.setCategory("notice");
            webSocketVo.setNoticeType("1");
            webSocketVo.setIsRead(0);
            webSocketVo.setText(com.alibaba.fastjson2.JSONObject.from(lifeNotice).toJSONString());

            webSocketProcess.sendMessage(receiverId, com.alibaba.fastjson2.JSONObject.from(webSocketVo).toJSONString());
        } catch (Exception e) {
            log.error("发送WebSocket通知失败，receiverId={}, error={}", receiverId, e.getMessage(), e);
        }
    }

    @Override
    public R<IPage<CommentAppealVo>> getAppealPage(Integer pageNum, Integer pageSize, Integer status,
                                                   String orderNumber, String userName, String userPhone, String lawyerName, String lawyerPhone,
                                                   String startTime, String endTime) {
        log.info("CommentAppealServiceImpl.getAppealPage?pageNum={}, pageSize={}, status={}, orderNumber={}, userName={}, userPhone={}, lawyerName={}, lawyerPhone={}, startTime={}, endTime={}",
                pageNum, pageSize, status, orderNumber, userName, userPhone, lawyerName, lawyerPhone, startTime, endTime);

        Page<CommentAppealVo> page = new Page<>(pageNum, pageSize);
        IPage<CommentAppealVo> pageResult = baseMapper.getAppealPageWithFilters(page, status, orderNumber, userName, userPhone, lawyerName, lawyerPhone, startTime, endTime);

        // 处理数据转换
        for (CommentAppealVo vo : pageResult.getRecords()) {
            processAppealVo(vo);
        }

        return R.data(pageResult);
    }

    @Override
    public R<CommentAppealVo> getAppealDetail(Integer id) {
        log.info("CommentAppealServiceImpl.getAppealDetail?id={}", id);

        if (id == null) {
            return R.fail("申诉ID不能为空");
        }

        // 查询申诉详情（包含评价和用户信息）
        CommentAppealVo vo = baseMapper.getAppealDetailById(id);
        if (vo == null) {
            return R.fail("申诉记录不存在或已被删除");
        }

        // 处理数据转换（复用历史列表的处理逻辑）
        processAppealVo(vo);

        return R.data(vo, "查询成功");
    }

    /**
     * 处理申诉VO数据转换（状态字符串、图片列表等）
     *
     * @param vo 申诉VO对象
     */
    private void processAppealVo(CommentAppealVo vo) {
        // 设置状态字符串
        if (vo.getStatus() != null) {
            switch (vo.getStatus()) {
                case 0:
                    vo.setStatusStr("审核中");
                    break;
                case 1:
                    vo.setStatusStr("已通过");
                    vo.setAppealResult("申诉成功");
                    break;
                case 2:
                    vo.setStatusStr("被驳回");
                    vo.setAppealResult("申诉失败");
                    break;
                default:
                    vo.setStatusStr("未知");
            }
        }

        // 处理申诉图片列表
        if (StringUtils.hasText(vo.getImgUrl())) {
            try {
                // 如果是 JSON 数组格式，解析为列表
                if (vo.getImgUrl().trim().startsWith("[")) {
                    List<String> imgList = JSON.parseArray(vo.getImgUrl(), String.class);
                    vo.setImgList(imgList != null ? imgList : new ArrayList<>());
                } else {
                    // 如果是单个 URL 或逗号分隔的字符串
                    List<String> imgList = new ArrayList<>();
                    String[] urls = vo.getImgUrl().split(",");
                    for (String url : urls) {
                        if (StringUtils.hasText(url.trim())) {
                            imgList.add(url.trim());
                        }
                    }
                    vo.setImgList(imgList);
                }
            } catch (Exception e) {
                log.warn("解析申诉图片失败，imgUrl={}", vo.getImgUrl(), e);
                List<String> imgList = new ArrayList<>();
                imgList.add(vo.getImgUrl());
                vo.setImgList(imgList);
            }
        } else {
            vo.setImgList(new ArrayList<>());
        }

        // 处理评价图片列表
        if (StringUtils.hasText(vo.getReviewImages())) {
            try {
                // 如果是 JSON 数组格式，解析为列表
                if (vo.getReviewImages().trim().startsWith("[")) {
                    List<String> reviewImgList = JSON.parseArray(vo.getReviewImages(), String.class);
                    vo.setReviewImgList(reviewImgList != null ? reviewImgList : new ArrayList<>());
                } else {
                    // 如果是单个 URL 或逗号分隔的字符串
                    List<String> reviewImgList = new ArrayList<>();
                    String[] urls = vo.getReviewImages().split(",");
                    for (String url : urls) {
                        if (StringUtils.hasText(url.trim())) {
                            reviewImgList.add(url.trim());
                        }
                    }
                    vo.setReviewImgList(reviewImgList);
                }
            } catch (Exception e) {
                log.warn("解析评价图片失败，reviewImages={}", vo.getReviewImages(), e);
                vo.setReviewImgList(new ArrayList<>());
            }
        } else {
            vo.setReviewImgList(new ArrayList<>());
        }
    }

    /**
     * 删除评价及该评价下的所有评论和回复
     *
     * @param reviewId 评价ID
     */
    private void deleteReviewAndRelatedData(Integer reviewId) {
        log.info("删除评价及关联数据，reviewId={}, userId={}", reviewId);

        if (reviewId == null) {
            log.warn("评价ID为空，无法删除");
            return;
        }

        try {
            // 1. 查询该评价下的所有评论
            LambdaQueryWrapper<ReviewComment> commentWrapper = new LambdaQueryWrapper<>();
            commentWrapper.eq(ReviewComment::getReviewId, reviewId)
                    .eq(ReviewComment::getDeleteFlag, 0);
            List<ReviewComment> comments = reviewCommentService.list(commentWrapper);

            // 2. 删除每个评论下的所有回复
            for (ReviewComment comment : comments) {
                // 删除评论下的所有回复（逻辑删除）
                LambdaUpdateWrapper<ReviewComment> replyUpdateWrapper = new LambdaUpdateWrapper<>();
                replyUpdateWrapper.eq(ReviewComment::getHeadId, comment.getId())
                        .eq(ReviewComment::getHeadType, 1)
                        .eq(ReviewComment::getDeleteFlag, 0);
                replyUpdateWrapper.set(ReviewComment::getDeleteFlag, 1);
                replyUpdateWrapper.set(ReviewComment::getUpdatedTime, new Date());
                reviewCommentService.update(replyUpdateWrapper);
                log.info("删除评论下的回复，commentId={}, 回复数已删除", comment.getId());
            }

            // 3. 删除所有评论（逻辑删除）
            for (ReviewComment comment : comments) {
                comment.setDeleteFlag(1);
                comment.setUpdatedTime(new Date());
                reviewCommentService.updateById(comment);
            }
            log.info("删除评价下的评论，reviewId={}, 评论数={}", reviewId, comments.size());

            // 4. 删除评价本身（逻辑删除）
            OrderReview review = orderReviewService.getById(reviewId);
            if (review != null && review.getDeleteFlag() == 0) {
                review.setDeleteFlag(1);
                review.setUpdatedTime(new Date());
                orderReviewService.updateById(review);
                log.info("删除评价成功，reviewId={}", reviewId);
            } else {
                log.warn("评价不存在或已删除，reviewId={}", reviewId);
            }
        } catch (Exception e) {
            log.error("删除评价及关联数据失败，reviewId={}, error={}", reviewId, e.getMessage(), e);
            throw new RuntimeException("删除评价及关联数据失败：" + e.getMessage(), e);
        }
    }

    @Override
    public List<CommentAppealVo> getAppealHistory(Integer pageNum, Integer pageSize, Integer status, Integer lawyerUserId) {
        log.info("CommentAppealServiceImpl.getAppealHistory?pageNum={}, pageSize={}, status={}, lawyerUserId={}",
                pageNum, pageSize, status, lawyerUserId);
        List<CommentAppealVo> appealList = new ArrayList<>();
        //status 3 查全部
        if (status != null && status == 3) {
            appealList = baseMapper.getAppealHistoryList(null, lawyerUserId);
        } else {
            // 查询申诉历史列表
            appealList = baseMapper.getAppealHistoryList(status, lawyerUserId);
        }

        // 防止空指针异常：如果查询结果为null，初始化为空列表
        if (appealList == null) {
            appealList = new ArrayList<>();
        }

        // 处理数据转换（图片列表等）
        for (CommentAppealVo vo : appealList) {
            if (vo != null) {
                processAppealVo(vo);
            }
        }

        ListToPage.setPage(appealList, pageNum, pageSize);

        return appealList;
    }
}
