package shop.alien.lawyer.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;
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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.math.RandomUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
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.dto.LawyerConsultationOrderDto;
import shop.alien.entity.store.dto.PayStatusRequest;
import shop.alien.entity.store.vo.LawyerConsultationOrderVO;
import shop.alien.entity.store.vo.OrderRevenueVO;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.lawyer.config.WebSocketProcess;
import shop.alien.lawyer.payment.PaymentStrategyFactory;
import shop.alien.lawyer.service.LawyerConsultationOrderService;
import shop.alien.lawyer.service.LawyerUserService;
import shop.alien.lawyer.service.OrderExpirationService;
import shop.alien.lawyer.util.DateUtils;
import shop.alien.mapper.*;
import shop.alien.util.common.constant.LawyerStatusEnum;
import shop.alien.util.type.LifeMessageUtil;
import shop.alien.util.type.LifeNoticeUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 咨询订单 服务实现类
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Transactional
@Service
@RequiredArgsConstructor
public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsultationOrderMapper, LawyerConsultationOrder> implements LawyerConsultationOrderService {

    private final LawyerConsultationOrderMapper consultationOrderMapper;
    private final LawyerUserService lawyerUserService;
    private final LawyerServiceAreaMapper lawyerServiceAreaMapper;
    private final LawyerUserMapper lawyerUserMapper;
    private final LawyerExpertiseAreaMapper lawyerExpertiseAreaMapper;
    private final OrderExpirationService orderExpirationService;
//    private final AliApi aliApi;
    private final LawFirmMapper lawFirmMapper;
    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeNoticeUtil lifeNoticeUtil;
    private final LifeUserMapper lifeUserMapper;
    private final WebSocketProcess webSocketProcess;

    private final LifeMessageMapper lifeMessageMapper;
    private final LifeMessageUtil lifeMessageUtil;
    private final StoreCommentMapper storeCommentMapper;
    private final LawyerUserViolationMapper lawyerUserViolationMapper;
    private final CommentAppealMapper commentAppealMapper;
    private final OrderReviewMapper orderReviewMapper;


    private final PaymentStrategyFactory paymentStrategyFactory;

    /**
     * 系统发送者ID
     */
    private static final String SYSTEM_SENDER_ID = "system";

    /**
     * 删除标记：未删除
     */
    private static final Integer DELETE_FLAG_NOT_DELETED = 0;

    /**
     * 金额单位转换：分转元
     */
    private static final int FEN_TO_YUAN = 100;

    /**
     * 默认价格字符串（当所有收费字段都为空时）
     */
    private static final String DEFAULT_PRICE_STR = "";

    /**
     * 默认格式化价格（当价格为null时）
     */
    private static final String DEFAULT_FORMATTED_PRICE = "0";

    /**
     * 价格格式：分钟收费
     */
    private static final String PRICE_FORMAT_MINUTE = "￥%s/%d分钟";

    /**
     * 价格格式：次数收费
     */
    private static final String PRICE_FORMAT_TIME = "￥%s/%d次";

    /**
     * 小数位数：保留2位小数
     */
    private static final int DECIMAL_SCALE = 2;

    @Value("${order.coefficients}")
    private String coefficients;

    @Override
    public R<IPage<LawyerConsultationOrderVO>> getConsultationOrderList(int pageNum, int pageSize, String orderNumber,
                                                                        Integer clientUserId, Integer lawyerUserId, String lawyerName, Integer orderStatus) {
        log.info("LawyerConsultationOrderServiceImpl.getConsultationOrderList?pageNum={},pageSize={},orderNumber={},clientUserId={},lawyerUserId={},lawyerName={},orderStatus={}",
                pageNum, pageSize, orderNumber, clientUserId, lawyerUserId, lawyerName, orderStatus);

        // 創建分頁對象
        Page<LawyerConsultationOrderVO> page = new Page<>(pageNum, pageSize);

        // 如果按律師姓名搜索，先查詢匹配的律師ID列表
        List<Integer> lawyerUserIds = null;
        if (StringUtils.hasText(lawyerName)) {
            LambdaQueryWrapper<LawyerUser> lawyerQueryWrapper = new LambdaQueryWrapper<>();
            lawyerQueryWrapper.eq(LawyerUser::getDeleteFlag, 0);
            lawyerQueryWrapper.like(LawyerUser::getName, lawyerName);
            List<LawyerUser> lawyerUsers = lawyerUserService.list(lawyerQueryWrapper);
            if (lawyerUsers != null && !lawyerUsers.isEmpty()) {
                lawyerUserIds = lawyerUsers.stream()
                        .map(LawyerUser::getId)
                        .collect(Collectors.toList());
            } else {
                // 如果沒有找到匹配的律師，返回空結果
                Page<LawyerConsultationOrderVO> emptyPage = new Page<>(pageNum, pageSize);
                emptyPage.setRecords(Collections.emptyList());
                emptyPage.setTotal(0);
                return R.data(emptyPage);
            }
        }

        // 使用JOIN查詢，直接聯查律師信息
        IPage<LawyerConsultationOrderVO> voPage = consultationOrderMapper.getConsultationOrderListWithLawyer(
                page, orderNumber, clientUserId, lawyerUserId, lawyerName, orderStatus, lawyerUserIds);

        // 為待支付訂單計算倒計時（30分鐘有效期）
        if (voPage != null && voPage.getRecords() != null) {
            Date now = new Date();
            long validitySeconds = 30 * 60; // 30分鐘 = 1800秒

            for (LawyerConsultationOrderVO vo : voPage.getRecords()) {
                // 僅對待支付訂單（orderStatus=0）計算倒計時
                if (vo.getOrderStatus() != null && vo.getOrderStatus() == 0) {
                    Date orderTime = vo.getOrderTime();
                    if (orderTime != null) {
                        long elapsedSeconds = (now.getTime() - orderTime.getTime()) / 1000;
                        long remainingSeconds = validitySeconds - elapsedSeconds;
                        // 如果已過期，設置為0
                        vo.setCountdownSeconds(Math.max(0, remainingSeconds));
                    } else {
                        vo.setCountdownSeconds(0L);
                    }
                } else {
                    // 非待支付訂單，倒計時為null
                    vo.setCountdownSeconds(null);
                }
            }
        }

        return R.data(voPage);
    }

    /**
     * 將訂單分頁結果轉換為VO並填充律師信息
     */
    private IPage<LawyerConsultationOrderVO> convertToVO(IPage<LawyerConsultationOrder> pageResult) {
        // 創建VO分頁對象
        Page<LawyerConsultationOrderVO> voPage = new Page<>(pageResult.getCurrent(), pageResult.getSize(), pageResult.getTotal());

        List<LawyerConsultationOrder> records = pageResult.getRecords();
        if (records == null || records.isEmpty()) {
            voPage.setRecords(Collections.emptyList());
            return voPage;
        }

        // 收集所有律師ID
        Set<Integer> lawyerUserIds = records.stream()
                .map(LawyerConsultationOrder::getLawyerUserId)
                .filter(id -> id != null)
                .collect(Collectors.toSet());

        // 批量查詢律師信息
        Map<Integer, LawyerUser> lawyerMap = new HashMap<>();
        if (!lawyerUserIds.isEmpty()) {
            LambdaQueryWrapper<LawyerUser> lawyerWrapper = new LambdaQueryWrapper<>();
            lawyerWrapper.in(LawyerUser::getId, lawyerUserIds);
            lawyerWrapper.eq(LawyerUser::getDeleteFlag, 0);
            List<LawyerUser> lawyerUsers = lawyerUserService.list(lawyerWrapper);
            if (lawyerUsers != null && !lawyerUsers.isEmpty()) {
                lawyerMap = lawyerUsers.stream()
                        .collect(Collectors.toMap(LawyerUser::getId, lawyer -> lawyer, (k1, k2) -> k1));
            }
        }

        // 批量查询律所信息
        Map<Integer, LawFirm> lawFirmMap = new HashMap<>();
        if (lawyerMap != null && !lawyerMap.isEmpty()) {
            Set<Integer> firmIds = lawyerMap.values().stream()
                    .map(LawyerUser::getFirmId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            if (!firmIds.isEmpty()) {
                List<LawFirm> lawFirms = lawFirmMapper.selectBatchIds(firmIds);
                if (lawFirms != null) {
                    lawFirmMap = lawFirms.stream()
                            .filter(firm -> firm.getDeleteFlag() == null || firm.getDeleteFlag() == 0)
                            .collect(Collectors.toMap(LawFirm::getId, firm -> firm, (k1, k2) -> k1));
                }
            }
        }

        // 轉換為VO並填充律師信息
        final Map<Integer, LawyerUser> finalLawyerMap = lawyerMap;
        final Map<Integer, LawFirm> finalLawFirmMap = lawFirmMap;
        List<LawyerConsultationOrderVO> voList = records.stream()
                .map(order -> {
                    LawyerConsultationOrderVO vo = new LawyerConsultationOrderVO();
                    // 複製訂單基本信息
                    BeanUtils.copyProperties(order, vo);

                    // 填充律師信息
                    LawyerUser lawyer = finalLawyerMap.get(order.getLawyerUserId());
                    if (lawyer != null) {
                        vo.setLawyerName(lawyer.getName());
                        vo.setLawyerPhone(lawyer.getPhone());
                        vo.setLawyerEmail(lawyer.getEmail());
                        vo.setLawyerCertificateNo(lawyer.getLawyerCertificateNo());
                        // 通过firm_id查询律所名称
                        if (lawyer.getFirmId() != null) {
                            LawFirm lawFirm = finalLawFirmMap.get(lawyer.getFirmId());
                            vo.setLawFirm(lawFirm != null ? lawFirm.getFirmName() : null);
                        } else {
                            vo.setLawFirm(null);
                        }
                        vo.setPracticeYears(lawyer.getPracticeYears());
                        vo.setSpecialtyFields(lawyer.getSpecialtyFields());
                        vo.setCertificationStatus(lawyer.getCertificationStatus());
                        vo.setServiceScore(lawyer.getServiceScore());
                        vo.setServiceCount(lawyer.getServiceCount());
                        vo.setLawyerConsultationFee(lawyer.getConsultationFee());
                        vo.setProvince(lawyer.getProvince());
                        vo.setCity(lawyer.getCity());
                        vo.setDistrict(lawyer.getDistrict());
                        vo.setAddress(lawyer.getAddress());
                        vo.setHeadImg(lawyer.getHeadImg());
                        vo.setNickName(lawyer.getNickName());
                        vo.setPersonalIntroduction(lawyer.getPersonalIntroduction());
                    }

                    return vo;
                })
                .collect(Collectors.toList());

        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public R<LawyerConsultationOrder> addConsultationOrder(LawyerConsultationOrder consultationOrder) {
        log.info("LawyerConsultationOrderServiceImpl.addConsultationOrder?consultationOrder={}", consultationOrder);
        boolean result = this.save(consultationOrder);
        if (result) {
            return R.data(consultationOrder);
        }
        return R.fail("新增失败");
    }

    /**
     * 编辑咨询订单
     * <p>
     * 编辑前会进行以下校验：
     * 1. 参数校验：订单ID不能为空
     * 2. 订单存在性校验：订单必须存在
     * 3. 订单状态校验：已完成的订单不允许修改关键信息
     * </p>
     *
     * @param consultationOrder 咨询订单
     * @return 编辑结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<LawyerConsultationOrder> editConsultationOrder(LawyerConsultationOrder consultationOrder) {
        Integer orderId = consultationOrder.getId();
        log.info("开始编辑咨询订单，订单ID={}", orderId);

        // 参数校验：订单ID不能为空
        if (orderId == null) {
            log.warn("编辑咨询订单失败：订单ID为空");
            return R.fail("订单ID不能为空");
        }

        // 查询订单信息，验证订单是否存在
        LawyerConsultationOrder existingOrder = consultationOrderMapper.selectById(orderId);
        if (existingOrder == null) {
            log.warn("编辑咨询订单失败：订单不存在，订单ID={}", orderId);
            return R.fail("订单不存在");
        }

        // 记录修改前的订单状态
        Integer oldOrderStatus = existingOrder.getOrderStatus();
        Integer oldPaymentStatus = existingOrder.getPaymentStatus();
        Integer newOrderStatus = consultationOrder.getOrderStatus();
        Integer newPaymentStatus = consultationOrder.getPaymentStatus();

        log.info("编辑咨询订单，订单ID={}, 订单编号={}, 原订单状态={}, 新订单状态={}, 原支付状态={}, 新支付状态={}",
                orderId, existingOrder.getOrderNumber(), oldOrderStatus, newOrderStatus,
                oldPaymentStatus, newPaymentStatus);

        // 订单状态校验：已完成的订单不允许修改关键信息（订单状态、支付状态、订单金额等）
        Integer completedStatus = LawyerStatusEnum.COMPLETE.getStatus(); // 3:已完成
        if (completedStatus.equals(oldOrderStatus)) {
            // 如果订单已完成，只允许修改评价相关字段（rating, comment）
            if (newOrderStatus != null && !newOrderStatus.equals(oldOrderStatus)) {
                log.warn("编辑咨询订单失败：订单已完成，不允许修改订单状态，订单ID={}, 订单编号={}",
                        orderId, existingOrder.getOrderNumber());
                return R.fail("订单已完成，不允许修改订单状态");
            }
            if (newPaymentStatus != null && !newPaymentStatus.equals(oldPaymentStatus)) {
                log.warn("编辑咨询订单失败：订单已完成，不允许修改支付状态，订单ID={}, 订单编号={}",
                        orderId, existingOrder.getOrderNumber());
                return R.fail("订单已完成，不允许修改支付状态");
            }
            if (consultationOrder.getOrderAmount() != null &&
                    !consultationOrder.getOrderAmount().equals(existingOrder.getOrderAmount())) {
                log.warn("编辑咨询订单失败：订单已完成，不允许修改订单金额，订单ID={}, 订单编号={}",
                        orderId, existingOrder.getOrderNumber());
                return R.fail("订单已完成，不允许修改订单金额");
            }
        }

        // 已取消的订单不允许修改为其他状态（除非是管理员操作，这里暂不限制）
        Integer cancelStatus = LawyerStatusEnum.CANCEL.getStatus(); // 4:已取消
        if (cancelStatus.equals(oldOrderStatus) && newOrderStatus != null &&
                !cancelStatus.equals(newOrderStatus)) {
            log.warn("编辑咨询订单警告：订单已取消，尝试修改订单状态，订单ID={}, 订单编号={}, 原状态={}, 新状态={}",
                    orderId, existingOrder.getOrderNumber(), oldOrderStatus, newOrderStatus);
            // 这里可以根据业务需求决定是否允许，暂时允许修改
        }

        // 如果订单状态从待支付变为已支付，需要更新支付时间
        Integer waitPayStatus = LawyerStatusEnum.WAIT_PAY.getStatus(); // 0:待支付
        if (waitPayStatus.equals(oldOrderStatus) && newOrderStatus != null &&
                !waitPayStatus.equals(newOrderStatus) && newPaymentStatus != null && newPaymentStatus == 1) {
            if (consultationOrder.getPaymentTime() == null) {
                consultationOrder.setPaymentTime(new Date());
                log.info("订单状态从待支付变为已支付，自动设置支付时间，订单ID={}, 订单编号={}",
                        orderId, existingOrder.getOrderNumber());
            }
        }

        // 设置更新时间
        consultationOrder.setUpdatedTime(new Date());

        // 执行更新操作
        boolean result = this.updateById(consultationOrder);
        if (result) {
            log.info("编辑咨询订单成功，订单ID={}, 订单编号={}, 原订单状态={}, 新订单状态={}",
                    orderId, existingOrder.getOrderNumber(), oldOrderStatus, newOrderStatus);
            // 重新查询更新后的订单信息
            LawyerConsultationOrder updatedOrder = consultationOrderMapper.selectById(orderId);
            return R.data(updatedOrder != null ? updatedOrder : consultationOrder);
        } else {
            log.error("编辑咨询订单失败：数据库更新失败，订单ID={}, 订单编号={}",
                    orderId, existingOrder.getOrderNumber());
            return R.fail("修改失败");
        }
    }

    /**
     * 删除咨询订单
     * <p>
     * 删除前会进行以下校验：
     * 1. 参数校验：订单ID不能为空
     * 2. 订单存在性校验：订单必须存在
     * 3. 订单状态校验：进行中的订单不允许删除
     * 4. 如果订单是待支付状态，会取消Redis中的支付超时计时器
     * </p>
     *
     * @param id 订单ID
     * @return 删除结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> deleteConsultationOrder(Integer id) {
        log.info("开始删除咨询订单，订单ID={}", id);

        // 参数校验
        if (id == null) {
            log.warn("删除咨询订单失败：订单ID为空");
            return R.fail("订单ID不能为空");
        }

        // 查询订单信息
        LawyerConsultationOrder order = consultationOrderMapper.selectById(id);
        if (order == null) {
            log.warn("删除咨询订单失败：订单不存在，订单ID={}", id);
            return R.fail("订单不存在");
        }

        // 检查订单状态：进行中的订单不允许删除
        Integer orderStatus = order.getOrderStatus();
        Integer inProgressStatus = LawyerStatusEnum.INPROGRESS.getStatus(); // 2:进行中
        if (inProgressStatus.equals(orderStatus)) {
            log.warn("删除咨询订单失败：订单进行中，不允许删除，订单ID={}, 订单编号={}",
                    id, order.getOrderNumber());
            return R.fail("订单进行中，不允许删除");
        }

        // 如果订单是待支付状态，取消Redis中的订单支付超时计时
        Integer waitPayStatus = LawyerStatusEnum.WAIT_PAY.getStatus(); // 0:待支付
        if (waitPayStatus.equals(orderStatus) && order.getOrderNumber() != null) {
            try {
                orderExpirationService.cancelOrderPaymentTimeout(order.getOrderNumber());
                log.info("已取消订单支付超时计时，订单编号={}", order.getOrderNumber());
            } catch (Exception e) {
                log.error("取消订单支付超时计时失败，订单编号={}", order.getOrderNumber(), e);
                // 继续执行删除操作，不因取消计时器失败而中断
            }
        }

        // 执行删除操作
        boolean result = this.removeById(id);
        if (result) {
            log.info("删除咨询订单成功，订单ID={}, 订单编号={}", id, order.getOrderNumber());
            return R.data(true, "删除成功");
        } else {
            log.error("删除咨询订单失败：数据库操作失败，订单ID={}, 订单编号={}", id, order.getOrderNumber());
            return R.fail("删除失败");
        }
    }

    /*@Override
    public R<Map<String, Object>> startConsultation(Integer lawyerId, String question, String sessionId, Integer clientUserId, Integer problemScenarioId) {
        log.info("LawyerConsultationOrderServiceImpl.startConsultation?lawyerId={},question={},sessionId={},clientUserId={},problemScenarioId={}",
                lawyerId, question, sessionId, clientUserId, problemScenarioId);

        // 创建咨询订单
        LawyerConsultationOrder order = new LawyerConsultationOrder();
        order.setLawyerUserId(lawyerId);
        order.setClientUserId(clientUserId);
        order.setProblemScenarioId(problemScenarioId);
        order.setProblemDescription(question);
        order.setOrderStatus(0);  // 待支付
        order.setPaymentStatus(0);  // 未支付

        boolean saved = this.save(order);
        if (!saved) {
            return R.fail("创建咨询订单失败");
        }

        Map<String, Object> result = new HashMap<>();
        result.put("consultationId", order.getId());
        result.put("lawyerId", lawyerId);
        result.put("status", "pending");  // pending(待响应), active(进行中), closed(已结束)
        result.put("createTime", order.getCreatedTime() != null ?
                new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(order.getCreatedTime()) : "");

        return R.data(result);
    }*/


    @Override
    public R<LawyerConsultationOrderDto> consultNow(LawyerConsultationOrder lawyerConsultationOrder) {
            log.info("LawyerConsultationOrderServiceImpl.consultNow?lawyerConsultationOrder={}", lawyerConsultationOrder);

        // 参数校验
        if (lawyerConsultationOrder == null) {
            log.warn("创建咨询订单失败：订单信息为空");
            return R.fail("订单信息不能为空");
        }

        Integer clientUserId = lawyerConsultationOrder.getClientUserId();
        Integer lawyerUserId = lawyerConsultationOrder.getLawyerUserId();
        Integer orderAmount = lawyerConsultationOrder.getOrderAmount();

        if (clientUserId == null || clientUserId <= 0) {
            log.warn("创建咨询订单失败：客户端用户ID无效，clientUserId={}", clientUserId);
            return R.fail("客户端用户ID不能为空");
        }

        if (lawyerUserId == null || lawyerUserId <= 0) {
            log.warn("创建咨询订单失败：律师用户ID无效，lawyerUserId={}", lawyerUserId);
            return R.fail("律师用户ID不能为空");
        }

        if (orderAmount == null || orderAmount <= 0) {
            log.warn("创建咨询订单失败：订单金额无效，orderAmount={}", orderAmount);
            return R.fail("订单金额不能为空且必须大于0");
        }

         LawyerUser  lawuer = lawyerUserMapper.selectById(lawyerUserId);



        // 创建订单DTO对象
        LawyerConsultationOrderDto order = new LawyerConsultationOrderDto();
        Date now = new Date();

        // 设置订单基本信息
        order.setClientUserId(clientUserId);
        order.setLawyerUserId(lawyerUserId);
        order.setProblemScenarioId(lawyerConsultationOrder.getProblemScenarioId());
        order.setProblemDescription(lawyerConsultationOrder.getProblemDescription());
        order.setOrderAmount(orderAmount);
        order.setAlipayNo(lawyerConsultationOrder.getAlipayNo());
        order.setOrderStr(lawyerConsultationOrder.getOrderStr());
        order.setPlaceId(lawyerConsultationOrder.getPlaceId());
        order.setPayType(lawyerConsultationOrder.getPayType());

        if (lawyerConsultationOrder.getChargeMinute() != null) {
            order.setChargeMinute(lawyerConsultationOrder.getChargeMinute());
        }
        if (lawyerConsultationOrder.getMinuteNum() != null) {
            order.setMinuteNum(lawyerConsultationOrder.getMinuteNum());
        }
        if (lawyerConsultationOrder.getChargeTime() != null) {
            order.setChargeTime(lawyerConsultationOrder.getChargeTime());
        }
        if (lawyerConsultationOrder.getTimeNum() != null) {
            order.setTimeNum(lawyerConsultationOrder.getTimeNum());
        }
        if (lawuer != null) {
            if (lawuer.getFirmId() != null){
                order.setPlaceId(lawuer.getFirmId());
            }
        }

       String serviceType =lawyerConsultationOrder.getServiceType();

        if (serviceType.contains("次")){
            //对serviceType进行截取，比如"10次"，想要10，则截取字符串"10"，并转换为整型10
            serviceType = serviceType.substring(0, serviceType.indexOf("次"));
            order.setTimeNum(Integer.valueOf(serviceType));

            order.setChargeTime(lawyerConsultationOrder.getPrice());
        }
        if (serviceType.contains("分钟")){
            serviceType = serviceType.substring(0, serviceType.indexOf("分钟"));
            order.setMinuteNum(Integer.valueOf(serviceType));
            order.setChargeMinute(lawyerConsultationOrder.getPrice());
        }


        // 设置订单状态
        order.setOrderStatus(0); // 待支付
        order.setPaymentStatus(0); // 未支付
        order.setOrderTime(now);
        order.setCreatedTime(now);
        order.setUpdatedTime(now);
        order.setDeleteFlag(0);

        // 生成订单编号：LAW + 年月日（8位数字）+ 随机5位数字
        String orderNumber = generateOrderNumber();
        order.setOrderNumber(!StringUtils.isEmpty(lawyerConsultationOrder.getOrderNumber())?lawyerConsultationOrder.getOrderNumber():orderNumber);
        log.info("生成订单编号：orderNumber={}", orderNumber);
        order.setAlipayNo(lawyerConsultationOrder.getOrderNumber());
        // 计算本单收益（平台收益）
        Integer consultationFee = calculateConsultationFee(lawyerUserId, orderAmount);
        order.setConsultationFee(consultationFee);
        log.info("计算咨询费用：lawyerUserId={}, orderAmount={}, consultationFee={}",
                lawyerUserId, orderAmount, consultationFee);

        // 计算律师收益（订单金额-平台收益）
        Integer lawyerEarnings =  orderAmount - consultationFee;
        order.setLawyerEarnings(lawyerEarnings);
        // 插入订单
        int insertCount = consultationOrderMapper.insertOrder(order);
        if (insertCount > 0) {
            log.info("创建咨询订单成功：orderNumber={}, orderId={}", orderNumber, order.getId());
            return R.data(order);
        } else {
            log.error("创建咨询订单失败：数据库插入失败，orderNumber={}", orderNumber);
            return R.fail("创建订单失败");
        }
    }

    /**
     * 生成订单编号
     * <p>
     * 格式：LAW + 年月日（8位数字）+ 随机5位数字
     * 示例：LAW2025011512345
     * </p>
     *
     * @return 订单编号
     */
    private String generateOrderNumber() {
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String randomStr = String.format("%05d", RandomUtils.nextInt(100000));
        return "LAW" + dateStr + randomStr;
    }

    /**
     * 计算咨询费用（本单收益）
     * <p>
     * 根据律所的平台佣金比例计算咨询费用
     * 如果律师没有关联律所或律所没有设置佣金比例，则使用默认佣金比例3%
     * </p>
     *
     * @param lawyerUserId 律师用户ID
     * @param orderAmount  订单金额（单位：分）
     * @return 咨询费用（单位：分）
     */
    private Integer calculateConsultationFee(Integer lawyerUserId, Integer orderAmount) {
        // 默认佣金比例：3%
        float defaultCommissionRate = 3.0F;
        float commissionRate = defaultCommissionRate;

        // 查询律师信息
        LawyerUser lawyerUser = lawyerUserMapper.selectById(lawyerUserId);
        if (lawyerUser != null) {
            // 获取律所信息
            Integer firmId = lawyerUser.getFirmId();
            if (firmId != null && firmId > 0) {
                LawFirm lawyerFirm = lawFirmMapper.selectById(firmId);
                if (lawyerFirm != null && lawyerFirm.getPlatformCommissionRatio() != null
                        && lawyerFirm.getPlatformCommissionRatio().floatValue() > 0) {
                    commissionRate = lawyerFirm.getPlatformCommissionRatio().floatValue();
                }
            }
        }

        // 计算咨询费用：订单金额 * 佣金比例 / 100，四舍五入
        int consultationFee = Math.round(orderAmount * commissionRate / 100);
        return consultationFee;
    }

    /**
     * 更新订单支付状态
     * <p>
     * 根据支付状态更新订单信息，包括订单状态、支付状态、支付时间等
     * </p>
     *
     * @param request 支付状态更新请求对象，包含订单编号、支付状态、订单状态等信息，不能为空
     * @return 更新结果，成功返回订单信息，失败返回错误信息
     */
    @Override
    public R<LawyerConsultationOrderDto> payStatus(PayStatusRequest request) {
        log.info("LawyerConsultationOrderServiceImpl.payStatus?orderNumber={},paymentStatus={},orderStatus={},payType={}",
                request.getOrderNumber(), request.getPaymentStatus(), request.getOrderStatus(), request.getPayType());

        LawyerConsultationOrderDto order = new LawyerConsultationOrderDto();
        if (null != request.getOrderStr()){
            order.setOrderStr(request.getOrderStr());
        }
        if (null != request.getAlipayNo()){
            order.setAlipayNo(request.getAlipayNo());
        }
        if (null != request.getPayType()){
            order.setPayType(request.getPayType());
        }
        order.setOrderNumber(request.getOrderNumber());
        order.setPaymentStatus(1);
        order.setOrderStatus(1);
        order.setUpdatedTime(new Date());
        order.setDeleteFlag(0);
        order.setPaymentTime(new Date());
        order.setStartTime(new Date());
//        LocalDateTime now = LocalDateTime.now();
//        LocalDateTime validityDateTime = now.plusDays(7)
//                .withHour(0)
//                .withMinute(0)
//                .withSecond(0)
//                .withNano(0);
//        order.setValidityPeriod(Date.from(validityDateTime.atZone(ZoneId.systemDefault()).toInstant()));
//        boolean result = this.updateById(order);
        Integer result = consultationOrderMapper.updateOrder(order);

        if (result > 0) {
            return R.data(order);
        }
        return R.fail("失败");
    }

    /**
     * 根据用户ID查询订单列表（包含律师信息）
     *
     * @param pageNum     页码
     * @param pageSize    页容量
     * @param userId      用户ID
     * @param orderStatus 订单状态
     * @param lawyerName  律师姓名（支持模糊查询）
     * @return 分页订单列表
     */
    @Override
    public Map<String, Object> getConsultationOrderListById(int pageNum, int pageSize,
                                                             String userId, String orderStatus,
                                                             String lawyerName) {
        log.info("查询咨询订单信息（律师端）- pageNum={}, pageSize={}, userId={}, orderStatus={}, lawyerName={}",
                pageNum, pageSize, userId, orderStatus, lawyerName);

        // 参数校验：用户ID不能为空
        if (!StringUtils.hasText(userId)) {
            log.warn("查询咨询订单信息失败：用户ID为空");
            return buildEmptyResultMap(pageNum, pageSize);
        }

        // 创建分页对象
        Page<LawyerConsultationOrderVO> page = new Page<>(pageNum, pageSize);

        // 构建查询条件
        QueryWrapper<LawyerConsultationOrderVO> queryWrapper = buildOrderQueryWrapper(
                lawyerName, orderStatus, userId);
        QueryWrapper<LawyerConsultationOrderVO> statisticsWrapper = buildStatisticsQueryWrapper(
                lawyerName, userId);

        // 查询订单列表
        IPage<LawyerConsultationOrderVO> voPage = consultationOrderMapper.getLawyerConsultationOrderList(
                page, queryWrapper);

        if (voPage != null) {
            // 填充法律场景信息和倒计时
            fillLegalSceneArea(voPage);
            calculateCountdownForPendingOrders(voPage);

            //填充未读消息
            fillUnreadMessage(voPage,userId);

            // 设置订单价格字符串
            setOrderPriceStrForOrderList(voPage);

            // 设置评价状态
            setCommonStatusForOrderList(voPage);
        }

        // 判断工作日信息
        calculateWorkDayInfo(voPage);


        // 获取统计信息
        statisticsWrapper.groupBy("lco.order_status");
        List<Map<String, Object>> statisticsInfo = consultationOrderMapper.getLawyerStatisticsInfo(
                statisticsWrapper);

        // 构建状态统计Map并填充返回结果
        Map<Integer, Integer> statusCountMap = buildStatusCountMap(statisticsInfo);
        Map<String, Object> resultMap = buildOrderStatisticsResult(statusCountMap, voPage);

        return resultMap;
    }

    /**
     * 构建订单统计结果Map
     *
     * @param statusCountMap 状态统计Map
     * @param voPage        订单分页对象
     * @return 订单统计结果Map
     */
    private Map<String, Object> buildOrderStatisticsResult(Map<Integer, Integer> statusCountMap,
                                                            IPage<LawyerConsultationOrderVO> voPage) {
        Map<String, Object> resultMap = new HashMap<>(16);

        // 获取各状态订单数量
        Integer waitPayStatus = LawyerStatusEnum.WAIT_PAY.getStatus();
        int waitPayStatusCount = statusCountMap.getOrDefault(waitPayStatus, 0);

        Integer waitAcceptStatus = LawyerStatusEnum.WAIT_ACCEPT.getStatus();
        int waitAcceptStatusCount = statusCountMap.getOrDefault(waitAcceptStatus, 0);

        Integer inProgressStatus = LawyerStatusEnum.INPROGRESS.getStatus();
        int inProgressCount = statusCountMap.getOrDefault(inProgressStatus, 0);

        Integer completeStatus = LawyerStatusEnum.COMPLETE.getStatus();
        int completeCount = statusCountMap.getOrDefault(completeStatus, 0);

        Integer cancelStatus = LawyerStatusEnum.CANCEL.getStatus();
        int cancelStatusCount = statusCountMap.getOrDefault(cancelStatus, 0);

        Integer refundedStatus = LawyerStatusEnum.REFUNDED.getStatus();
        int refundedStatusCount = statusCountMap.getOrDefault(refundedStatus, 0);

        // 计算订单总数
        long totalOrderCount = (long) (waitPayStatusCount + waitAcceptStatusCount + inProgressCount
                + completeCount + cancelStatusCount + refundedStatusCount);

        // 填充返回结果
        resultMap.put("lawyerWaitPayStatusOrderCount", waitPayStatusCount);
        resultMap.put("lawyerWaitAcceptStatusOrderCount", waitAcceptStatusCount);
        resultMap.put("lawyerInProgressOrderCount", inProgressCount);
        resultMap.put("lawyerCompleteOrderCount", completeCount);
        resultMap.put("lawyerCancelStatusOrderCount", cancelStatusCount);
        resultMap.put("lawyerRefundedStatusOrderCount", refundedStatusCount);
        resultMap.put("total", totalOrderCount);

        // 设置订单列表
        List<LawyerConsultationOrderVO> orderList = (voPage != null && voPage.getRecords() != null)
                ? voPage.getRecords() : Collections.emptyList();
        resultMap.put("lawyerConsultationOrderList", orderList);

        return resultMap;
    }

    /**
     * 构建状态统计Map
     *
     * @param statisticsInfo 统计信息列表
     * @return 状态统计Map，key为订单状态，value为订单数量
     */
    private Map<Integer, Integer> buildStatusCountMap(List<Map<String, Object>> statisticsInfo) {
        Map<Integer, Integer> statusCountMap = new HashMap<>(16);
        if (CollectionUtils.isEmpty(statisticsInfo)) {
            return statusCountMap;
        }

        for (Map<String, Object> map : statisticsInfo) {
            Object statusObj = map.get("order_status");
            Object countObj = map.get("order_count");

            if (statusObj == null || countObj == null) {
                continue;
            }

            Integer status = (Integer) statusObj;
            // COUNT(*) 返回类型可能是Long
            Long countLong = (Long) countObj;
            statusCountMap.put(status, countLong.intValue());
        }

        return statusCountMap;
    }

    /**
     * 构建统计查询条件
     *
     * @param lawyerName 律师名称
     * @param userId     客户端用户ID
     * @return 统计查询条件包装器
     */
    private QueryWrapper<LawyerConsultationOrderVO> buildStatisticsQueryWrapper(String lawyerName,
                                                                                String userId) {
        QueryWrapper<LawyerConsultationOrderVO> queryWrapper = new QueryWrapper<>();
        if (StringUtils.hasText(lawyerName)) {
            queryWrapper.like("lu.name", lawyerName);
        }
        queryWrapper.eq("lco.client_user_id", userId);
        queryWrapper.eq("lco.delete_flag", 0);
        return queryWrapper;
    }


    /**
     * 构建空结果Map
     *
     * @param pageNum  页码
     * @param pageSize 页容量
     * @return 空结果Map
     */
    private Map<String, Object> buildEmptyResultMap(int pageNum, int pageSize) {
        Map<String, Object> resultMap = new HashMap<>(16);
        Page<LawyerConsultationOrderVO> emptyPage = new Page<>(pageNum, pageSize);
        emptyPage.setRecords(Collections.emptyList());
        emptyPage.setTotal(0);
        resultMap.put("lawyerWaitPayStatusOrderCount", 0);
        resultMap.put("lawyerWaitAcceptStatusOrderCount", 0);
        resultMap.put("lawyerInProgressOrderCount", 0);
        resultMap.put("lawyerCompleteOrderCount", 0);
        resultMap.put("lawyerCancelStatusOrderCount", 0);
        resultMap.put("lawyerRefundedStatusOrderCount", 0);
        resultMap.put("lawyerOrderCount", 0L);
        resultMap.put("lawyerConsultationOrderList", Collections.emptyList());
        return resultMap;
    }

    /**
     * 构建订单查询条件
     *
     * @param lawyerName 律师名称
     * @param orderStatus 订单状态
     * @param userId      客户端用户ID
     * @return 查询条件包装器
     */
    private QueryWrapper<LawyerConsultationOrderVO> buildOrderQueryWrapper(String lawyerName, String orderStatus,
                                                                           String userId) {
        QueryWrapper<LawyerConsultationOrderVO> queryWrapper = new QueryWrapper<>();

        // 订单状态条件
        if (StringUtils.hasText(orderStatus)) {
            queryWrapper.in("lco.order_status", Collections.singletonList(orderStatus));
        }

        // 律师名称条件
        if (StringUtils.hasText(lawyerName)) {
            queryWrapper.like("lu.name", lawyerName);
        }

        // 客户端用户ID条件
        queryWrapper.eq("lco.client_user_id", userId);

        // 删除标记条件
        queryWrapper.eq("lco.delete_flag", 0);

        // 排序条件：按创建时间倒序
        queryWrapper.orderByDesc("lco.created_time");
        return queryWrapper;
    }

    /**
     * 根据律师姓名查询律师ID列表
     *
     * @param lawyerName 律师姓名
     * @return 律师ID列表
     */
    private List<Integer> queryLawyerIdsByName(String lawyerName) {
        LambdaQueryWrapper<LawyerUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LawyerUser::getDeleteFlag, 0)
                .like(LawyerUser::getName, lawyerName);
        List<LawyerUser> lawyerUsers = lawyerUserService.list(queryWrapper);

        if (CollectionUtils.isEmpty(lawyerUsers)) {
            return Collections.emptyList();
        }

        return lawyerUsers.stream()
                .map(LawyerUser::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 填充律师法律场景到订单VO列表
     *
     * @param voPage 订单VO分页对象
     */
    private void fillLegalSceneArea(IPage<LawyerConsultationOrderVO> voPage) {
        List<LawyerConsultationOrderVO> orderList = voPage.getRecords();
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        // 提取所有律师ID
        List<Integer> lawyerIdList = orderList.stream()
                .map(LawyerConsultationOrderVO::getLawyerUserId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(lawyerIdList)) {
            return;
        }

        // 批量查询法律场景
        Map<String, List<String>> serviceAreaMap = getLawyerServiceArea(lawyerIdList);
        if (serviceAreaMap.isEmpty()) {
            return;
        }

        // 填充问题场景
        orderList.forEach(order -> {
            Integer lawyerUserId = order.getLawyerUserId();
            if (lawyerUserId != null) {
                String lawyerUserIdStr = String.valueOf(lawyerUserId);
                List<String> serviceAreaList = serviceAreaMap.get(lawyerUserIdStr);
                if (CollectionUtils.isNotEmpty(serviceAreaList)) {
                    order.setLawyerLegalProblemScenarioList(serviceAreaList);
                }
            }
        });
    }



    /**
     * 填充未读消息数量
     *
     * @param voPage 订单VO分页对象
     */
    private void fillUnreadMessage(IPage<LawyerConsultationOrderVO> voPage,String userId) {
        List<LawyerConsultationOrderVO> orderList = voPage.getRecords();
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        // 提取所有律师ID，并加上lawyer_前缀
        List<String> lawyerIdList = orderList.stream()
                .map(LawyerConsultationOrderVO::getLawyerPhone)
                .filter(Objects::nonNull)
                .map(phone -> "lawyer_" + phone)
                .distinct()
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(lawyerIdList)) {
            return;
        }

        LifeUser lifeUser = lifeUserMapper.selectById(userId);
        String phone = lifeUser.getUserPhone();

        LambdaQueryWrapper<LifeMessage> lifeMessageLambdaQueryWrapper = new LambdaQueryWrapper<>();
        lifeMessageUtil.applySenderInQuery(lifeMessageLambdaQueryWrapper, lawyerIdList);
        lifeMessageLambdaQueryWrapper.eq(LifeMessage::getDeleteFlag, 0);
        lifeMessageLambdaQueryWrapper.eq(LifeMessage::getIsRead, 0);
        lifeMessageUtil.applyReceiverQuery(lifeMessageLambdaQueryWrapper, "user_" + phone);
        List<LifeMessage> lifeMessageList = lifeMessageMapper.selectList(lifeMessageLambdaQueryWrapper);

        // 按照senderId进行分组，返回senderId和数量的map
        Map<String, Long> senderIdCountMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(lifeMessageList)){
            senderIdCountMap = lifeMessageList.stream()
                    .collect(Collectors.groupingBy(LifeMessage::getSenderId, Collectors.counting()));
        }

        for(LawyerConsultationOrderVO lawyerConsultationOrderVO : voPage.getRecords()){
            String lawyerPhone = "lawyer_" + lawyerConsultationOrderVO.getLawyerPhone();
            if(!senderIdCountMap.isEmpty() && senderIdCountMap.containsKey(lawyerPhone) && lawyerConsultationOrderVO.getOrderStatus() == 2){
                long messageCount = senderIdCountMap.get(lawyerPhone);
                lawyerConsultationOrderVO.setUnreadMessage(messageCount);
            } else {
                lawyerConsultationOrderVO.setUnreadMessage(0L);
            }
        }
    }


    /**
     * 批量查询律师问题场景
     *
     * @param lawyerIdList 律师ID列表
     * @return 律师问题场景Map，key为律师ID（String），value为问题场景名称列表
     */
    private Map<String, List<String>> getLawyerServiceArea(List<Integer> lawyerIdList) {
        Map<String, List<String>> serviceAreaMap = new HashMap<>();
        if (CollectionUtils.isEmpty(lawyerIdList)) {
            return serviceAreaMap;
        }

        QueryWrapper<LawyerServiceArea> wrapper = new QueryWrapper<>();
        wrapper.in("lsa.lawyer_user_id", lawyerIdList)
                .eq("lsa.delete_flag", 0)
                .eq("lsa.status", 1);

        List<Map<String, Object>> serviceAreaDataList = lawyerServiceAreaMapper.getLawyerLegalProblemScenarioList(wrapper);
        if (CollectionUtils.isEmpty(serviceAreaDataList)) {
            return serviceAreaMap;
        }

        for (Map<String, Object> row : serviceAreaDataList) {
            Object lawyerUserIdObj = row.get("lawyer_user_id");
            if (lawyerUserIdObj == null) {
                continue;
            }

            String lawyerUserId = String.valueOf(lawyerUserIdObj);
            String scenarioName = (String) row.get("name");
            String scenarioNameValue = StringUtils.hasText(scenarioName) ? scenarioName : "";

            serviceAreaMap.computeIfAbsent(lawyerUserId, k -> new ArrayList<>())
                    .add(scenarioNameValue);
        }

        return serviceAreaMap;
    }

    /**
     * 获取咨询订单详情
     *
     * @param lawyerOrderId 订单ID
     * @return 咨询订单详情VO
     */
    @Override
    public LawyerConsultationOrderVO getConsultationOrderDetail(String lawyerOrderId) {
        log.info("LawyerConsultationOrderServiceImpl.getConsultationOrderDetail?lawyerOrderId={}", lawyerOrderId);

        LawyerConsultationOrderVO orderVO = new LawyerConsultationOrderVO();

        // 参数校验
        if (!StringUtils.hasText(lawyerOrderId)) {
            return orderVO;
        }

        // 查询订单信息
        LawyerConsultationOrder order = consultationOrderMapper.selectById(lawyerOrderId);
        if (order == null) {
            return orderVO;
        }

        // 复制订单基本信息
        BeanUtils.copyProperties(order, orderVO);

        // 查询并填充律师信息
        Integer lawyerUserId = order.getLawyerUserId();
        if (lawyerUserId != null) {
            LawyerUser lawyerUser = lawyerUserMapper.selectById(lawyerUserId);
            if (lawyerUser != null) {
                fillLawyerInfo(orderVO, lawyerUser);
            }


            // 查询律师问题场景
            List<Integer> lawyerIdList = Collections.singletonList(lawyerUserId);
            Map<String, List<String>> serviceAreaMap = getLawyerServiceArea(lawyerIdList);
            String lawyerUserIdStr = String.valueOf(lawyerUserId);
            if (!serviceAreaMap.isEmpty() && serviceAreaMap.containsKey(lawyerUserIdStr)) {
                orderVO.setLawyerLegalProblemScenarioList(serviceAreaMap.get(lawyerUserIdStr));
            }
        }

        return orderVO;
    }

    /**
     * 取消律师咨询订单
     * <p>
     * 取消订单的业务逻辑：
     * 1. 参数校验：订单ID不能为空
     * 2. 订单存在性校验：订单必须存在
     * 3. 订单状态校验：已取消或已完成的订单不允许再次取消
     * 4. 如果订单是待支付状态，会取消Redis中的订单支付超时计时器
     * 5. 根据订单状态更新为相应状态：
     *    - 待接单状态：更新为已退款状态
     *    - 待支付状态：更新为已取消状态
     * </p>
     *
     * @param id 订单ID
     * @return 是否取消成功，true表示成功，false表示失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(String id) {
        log.info("开始取消订单，订单ID={}", id);
        try {
        // 1. 参数校验
        if (!StringUtils.hasText(id)) {
            log.warn("取消订单失败：订单ID为空");
            return false;
        }

        // 2. 查询订单信息
        LawyerConsultationOrder order = consultationOrderMapper.selectById(id);
        if (order == null) {
            log.warn("取消订单失败：订单不存在，订单ID={}", id);
            return false;
        }

        if (order.getOrderStatus() == 1 ) {
            Map<String, String> params=new HashMap<>();
            params.put("payType", "1".equals(order.getPayType()) ? "alipay" : "wechatPay");
            params.put("outTradeNo",order.getAlipayNo());
            params.put("totalAmount", String.valueOf(order.getOrderAmount()));

            params.put("refundAmount", String.valueOf(order.getOrderAmount()));
            if ("1".equals( order.getPayType())){
                params.put("refundAmount", new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100)).toString());
            }

            if ("2".equals( order.getPayType())){
                params.put("refundReason", "用户取消订单");
            }

            String refundResult =paymentStrategyFactory.getStrategy(params.get("payType")).handleRefund(params);

            if (!"调用成功".equals(refundResult)){
                log.warn("取消订单失败：订单取消失败，订单ID={}, 订单编号={}", id, order.getOrderNumber());
                return false;
            }
        }

        // 3. 订单状态校验
        Integer orderStatus = order.getOrderStatus();
        String orderNumber = order.getOrderNumber();
        
        // 提取订单状态常量，避免魔法值
        Integer cancelStatus = LawyerStatusEnum.CANCEL.getStatus();
        Integer completedStatus = LawyerStatusEnum.COMPLETE.getStatus();
        Integer waitAcceptStatus = LawyerStatusEnum.WAIT_ACCEPT.getStatus();
        Integer waitPayStatus = LawyerStatusEnum.WAIT_PAY.getStatus();
        Integer refundedStatus = LawyerStatusEnum.REFUNDED.getStatus();

        // 3.1 检查订单是否已取消（使用 Objects.equals 避免空指针异常）
        if (Objects.equals(cancelStatus, orderStatus)) {
            log.warn("取消订单失败：订单已取消，订单ID={}, 订单编号={}", id, orderNumber);
            return false;
        }

        // 3.2 检查订单是否已完成
        if (Objects.equals(completedStatus, orderStatus)) {
            log.warn("取消订单失败：订单已完成，不允许取消，订单ID={}, 订单编号={}", id, orderNumber);
            return false;
        }

        // 4. 如果订单是待支付状态，取消Redis中的订单支付超时计时器
        if (Objects.equals(waitPayStatus, orderStatus) && StringUtils.hasText(orderNumber)) {
            try {
                orderExpirationService.cancelOrderPaymentTimeout(orderNumber);
                log.info("已取消订单支付超时计时器，订单编号={}", orderNumber);
            } catch (Exception e) {
                log.error("取消订单支付超时计时器失败，订单编号={}，异常信息：{}", orderNumber, e.getMessage(), e);
                // 继续执行取消订单操作，不因取消计时器失败而中断
            }
        }

        // 5. 根据订单状态更新为相应状态
        Integer targetStatus;
        if (Objects.equals(waitAcceptStatus, orderStatus)) {
            // 待接单状态：更新为已退款状态
            targetStatus = refundedStatus;
            log.debug("待接单订单取消，将更新为已退款状态，订单ID={}", id);
        } else if (Objects.equals(waitPayStatus, orderStatus)) {
            // 待支付状态：更新为已取消状态
            targetStatus = cancelStatus;
            log.debug("待支付订单取消，将更新为已取消状态，订单ID={}", id);
        } else {
            log.warn("取消订单失败：订单状态不允许取消，订单ID={}, 订单编号={}, 订单状态={}", 
                    id, orderNumber, orderStatus);
            return false;
        }

        // 6. 更新订单状态
        LambdaUpdateWrapper<LawyerConsultationOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LawyerConsultationOrder::getId, id)
                .set(LawyerConsultationOrder::getOrderStatus, targetStatus)
                .set(LawyerConsultationOrder::getUpdatedTime, new Date());

        int updateCount = consultationOrderMapper.update(null, updateWrapper);
        boolean success = updateCount > 0;

        // 7. 记录操作结果
        if (success) {
            log.info("取消订单成功，订单ID={}, 订单编号={}, 原状态={}, 新状态={}", 
                    id, orderNumber, orderStatus, targetStatus);
        } else {
            log.error("取消订单失败：更新数据库失败，订单ID={}, 订单编号={}, 原状态={}, 目标状态={}", 
                    id, orderNumber, orderStatus, targetStatus);
        }

        return success;

        } catch (Exception e) {
            log.error("取消订单失败：订单ID={}, 错误信息={}", id,  e.getMessage());
            return false;
        }

    }

    /**
     * 查询咨询订单信息（律师端）
     *
     * @param pageNum   页码
     * @param pageSize  页容
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param lawyerId  律师ID
     * @return 订单信息Map，包含订单列表、总数、进行中数量、已完成数量
     */
    @Override
    public Map<String, Object> getLawyerConsultationOrderInfo(int pageNum, int pageSize, String startDate, String endDate, String clientUserName, String orderStatus, String lawyerId) {
        log.info("LawyerConsultationOrderServiceImpl.getLawyerConsultationOrderInfo?pageNum={},pageSize={},startDate={},endDate={},clientUserName={},lawyerId={}",
                pageNum, pageSize, startDate, endDate, clientUserName, lawyerId);

        Map<String, Object> resultMap = new HashMap<>();

        // 参数校验：律师ID不能为空
        if (!StringUtils.hasText(lawyerId)) {
            log.warn("查询咨询订单信息失败：律师ID为空");
            Page<LawyerConsultationOrderVO> emptyPage = new Page<>(pageNum, pageSize);
            emptyPage.setRecords(Collections.emptyList());
            emptyPage.setTotal(0);
            resultMap.put("lawyerOrderCount", 0L);
            resultMap.put("lawyerInProgressOrderCount", 0);
            resultMap.put("lawyerCompleteOrderCount", 0);
            resultMap.put("lawyerConsultationOrderList", Collections.emptyList());
            return resultMap;
        }

        // 创建分页对象
        Page<LawyerConsultationOrderVO> page = new Page<>(pageNum, pageSize);

        // 构建查询条件：查询进行中(2)和已完成(3)状态的订单
        QueryWrapper<LawyerConsultationOrderVO> queryWrapper = new QueryWrapper<>();
        QueryWrapper<LawyerConsultationOrderVO> queryStatisticsWrapper = new QueryWrapper<>();

        if (StringUtils.hasText(orderStatus)) {
            queryWrapper.in("lco.order_status", Collections.singletonList(orderStatus));
        } else {
            queryWrapper.in("lco.order_status", Arrays.asList("2", "3"));
        }
        queryWrapper.eq("lco.lawyer_user_id", lawyerId);
        queryStatisticsWrapper.eq("lco.lawyer_user_id", lawyerId);
        if (StringUtils.hasText(clientUserName)) {
            queryWrapper.like("lur.user_name", clientUserName);
            queryStatisticsWrapper.like("lur.user_name", clientUserName);
        }
        queryWrapper.eq("lco.delete_flag", 0);
        queryStatisticsWrapper.eq("lco.delete_flag", 0);
        queryWrapper.orderByDesc("lco.created_time");
        // 时间范围查询：如果开始时间和结束时间都存在，则进行范围查询
        if (StringUtils.hasText(startDate) && StringUtils.hasText(endDate)) {
            queryWrapper.between("lco.payment_time", startDate + " 00:00:00", endDate + " 23:59:59");
        }

        // 查询订单列表
        IPage<LawyerConsultationOrderVO> voPage = consultationOrderMapper.getLawyerConsultationOrderList(page, queryWrapper);

        // 填充律师问题场景信息
        if (voPage != null) {
            fillLegalSceneArea(voPage);
            // 为待支付订单计算倒计时（30分钟有效期）
            calculateCountdownForPendingOrders(voPage);
        }

        //获取统计信息
        queryStatisticsWrapper.groupBy("lco.order_status");
        List<Map<String, Object>> statisticsInfo = consultationOrderMapper.getLawyerStatisticsInfo(queryStatisticsWrapper);

        Map<Integer, Integer> statusCountMap = new HashMap<>();
        for (Map<String, Object> map : statisticsInfo) {
            Integer status = (Integer) map.get("order_status");
            Long countLong = (Long) map.get("order_count"); // COUNT(*) 返回类型可能是Long
            statusCountMap.put(status, countLong.intValue());
        }


        // 统计进行中订单数量
        int inProgressCount = statusCountMap.getOrDefault(2, 0);
        resultMap.put("lawyerInProgressOrderCount", inProgressCount);

        // 统计已完成订单数量
        int completeCount = statusCountMap.getOrDefault(3, 0);
        resultMap.put("lawyerCompleteOrderCount", completeCount);

        // 统计订单总数
        resultMap.put("lawyerOrderCount", inProgressCount + completeCount);

        // 设置订单列表
        List<LawyerConsultationOrderVO> orderList = voPage != null && voPage.getRecords() != null
                ? voPage.getRecords() : Collections.emptyList();
        resultMap.put("lawyerConsultationOrderList", orderList);

        return resultMap;
    }


    /**
     * 为待支付订单计算倒计时（30分钟有效期）
     *
     * @param voPage 订单分页对象
     */
    private void calculateCountdownForPendingOrders(IPage<LawyerConsultationOrderVO> voPage) {
        if (voPage == null || voPage.getRecords() == null) {
            return;
        }

        Date now = new Date();
        long validitySeconds = 30 * 60; // 30分钟 = 1800秒

        for (LawyerConsultationOrderVO vo : voPage.getRecords()) {
            // 仅对待支付订单（orderStatus=0）计算倒计时
            if (vo.getOrderStatus() != null && vo.getOrderStatus() == 0) {
                Date orderTime = vo.getOrderTime();
                if (orderTime != null) {
                    long elapsedSeconds = (now.getTime() - orderTime.getTime()) / 1000;
                    long remainingSeconds = validitySeconds - elapsedSeconds;
                    // 如果已过期，设置为0
                    vo.setCountdownSeconds(Math.max(0, remainingSeconds));
                } else {
                    vo.setCountdownSeconds(0L);
                }
            } else {
                // 非待支付订单，倒计时为null
                vo.setCountdownSeconds(null);
            }
        }
    }

    /**
     * 根据工作日判断是否可以申请退款/举报
     *
     * @param voPage 订单分页对象
     */
    private void calculateWorkDayInfo(IPage<LawyerConsultationOrderVO> voPage) {
        if (voPage == null || voPage.getRecords() == null) {
            return;
        }
        boolean isCanApplyRefund = DateUtils.getLastThreeWorkdaysRangeInfo(2);
        boolean isCanApplyViolation = DateUtils.getLastThreeWorkdaysRangeInfo(3);

        for (LawyerConsultationOrderVO vo : voPage.getRecords()) {
            if(isCanApplyRefund){
                vo.setIsCanApplyRefund("2");
            } else {
                vo.setIsCanApplyRefund("1");
            }

            if(isCanApplyViolation){
                vo.setIsCanApplyViolation("2");
            } else {
                vo.setIsCanApplyViolation("1");
            }
        }
    }

    /**
     * 填充律师信息到订单VO
     *
     * @param orderVO    订单VO对象
     * @param lawyerUser 律师用户对象
     */
    private void fillLawyerInfo(LawyerConsultationOrderVO orderVO, LawyerUser lawyerUser) {
        orderVO.setLawyerName(lawyerUser.getName());
        orderVO.setLawyerPhone(lawyerUser.getPhone());
        orderVO.setLawyerEmail(lawyerUser.getEmail());
        orderVO.setLawyerCertificateNo(lawyerUser.getLawyerCertificateNo());
        // 通过firm_id查询律所名称
        if (lawyerUser.getFirmId() != null) {
            LawFirm lawFirm = lawFirmMapper.selectById(lawyerUser.getFirmId());
            orderVO.setLawFirm(lawFirm != null && (lawFirm.getDeleteFlag() == null || lawFirm.getDeleteFlag() == 0) 
                    ? lawFirm.getFirmName() : null);
        } else {
            orderVO.setLawFirm(null);
        }
        orderVO.setPracticeYears(lawyerUser.getPracticeYears());
        orderVO.setSpecialtyFields(lawyerUser.getSpecialtyFields());
        orderVO.setCertificationStatus(lawyerUser.getCertificationStatus());
        orderVO.setServiceCount(lawyerUser.getServiceCount());
        orderVO.setServiceScore(lawyerUser.getServiceScore());
        orderVO.setLawyerConsultationFee(lawyerUser.getConsultationFee());
        orderVO.setProvince(lawyerUser.getProvince());
        orderVO.setCity(lawyerUser.getCity());
        orderVO.setDistrict(lawyerUser.getDistrict());
        orderVO.setAddress(lawyerUser.getAddress());
        orderVO.setHeadImg(lawyerUser.getHeadImg());
        orderVO.setNickName(lawyerUser.getNickName());
        orderVO.setPersonalIntroduction(lawyerUser.getPersonalIntroduction());
    }

    /**
     * 创建订单前的校验
     * <p>
     * 检查用户是否已存在咨询该律师的订单（订单状态为待接单或进行中）
     * </p>
     *
     * @param clientUserId 客户端用户ID，不能为空
     * @param lawyerUserId 律师用户ID，不能为空
     * @return 校验结果，如果已存在订单返回失败，否则返回成功
     */
    @Override
    public R<Map<String, String>> checkOrder(Integer clientUserId, Integer lawyerUserId) {
        log.info("LawyerConsultationOrderServiceImpl.checkOrder?clientUserId={},lawyerUserId={}", clientUserId, lawyerUserId);
        
        // 参数校验
        if (clientUserId == null) {
            log.warn("创建订单前校验失败：客户端用户ID为空");
            return R.fail("客户端用户ID不能为空");
        }
        
        if (lawyerUserId == null) {
            log.warn("创建订单前校验失败：律师用户ID为空");
            return R.fail("律师用户ID不能为空");
        }
        
        // 查询是否存在进行中的订单（订单状态为待接单或进行中）
        List<LawyerConsultationOrder> existingOrders = consultationOrderMapper.selectOrder(clientUserId, lawyerUserId);
        
        if (CollectionUtils.isNotEmpty(existingOrders)) {
            log.warn("创建订单前校验失败：用户已存在咨询该律师的订单，clientUserId={},lawyerUserId={}", clientUserId, lawyerUserId);
            return R.fail("您已存在咨询该律师的订单");
        }
        
        log.info("创建订单前校验成功：可以咨询该律师，clientUserId={},lawyerUserId={}", clientUserId, lawyerUserId);
        return R.success("可以咨询该律师");
    }

    /**
     * 获取律师订单收益统计
     * <p>
     * 统计三个维度的收益数据：
     * 1. 全部收益：所有已支付订单的订单总数和收益合计
     * 2. 进行中：订单状态=2（进行中）且已支付的订单总数和收益合计
     * 3. 已完成：订单状态=3（已完成）且已支付的订单总数和收益合计
     * </p>
     *
     * @param lawyerConsultationOrderVO 律师用户ID
     * @param lawyerConsultationOrderVO 开始时间（可选，用于筛选支付时间范围）
     * @param lawyerConsultationOrderVO 结束时间（可选，用于筛选支付时间范围）
     * @return 订单收益统计信息
     */
    @Override
    public R<Map<String, Object>> getOrderIncome(LawyerConsultationOrderVO lawyerConsultationOrderVO) {
        log.info("LawyerConsultationOrderController.getOrderIncome?lawyerConsultationOrderVO{}", lawyerConsultationOrderVO);

        // 参数校验
        if (lawyerConsultationOrderVO.getLawyerUserId() == null) {
            log.warn("查询订单收益失败：律师用户ID为空");
            return R.fail("律师用户ID不能为空");
        }

        Map<String, Object> resultMap = new HashMap<>();
        OrderRevenueVO revenueVO = new OrderRevenueVO();

        try {
            // 构建查询条件：查询已支付的订单（paymentStatus = 1）
            LambdaQueryWrapper<LawyerConsultationOrder> allRevenueWrapper = new LambdaQueryWrapper<>();
            allRevenueWrapper.eq(LawyerConsultationOrder::getLawyerUserId, lawyerConsultationOrderVO.getLawyerUserId())
                    .eq(LawyerConsultationOrder::getPaymentStatus, 1) // 已支付
                    .in(LawyerConsultationOrder::getOrderStatus, 2,3) // 订单状态=3（已完成）2（进行中）
                    .eq(LawyerConsultationOrder::getDeleteFlag, 0);
            
            // 添加时间段筛选条件（根据支付时间）
            if (lawyerConsultationOrderVO.getStartTimeNew() != null) {
                allRevenueWrapper.ge(LawyerConsultationOrder::getPaymentTime, lawyerConsultationOrderVO.getStartTimeNew());
            }
            if (lawyerConsultationOrderVO.getEndTimeNew()  != null) {
                allRevenueWrapper.le(LawyerConsultationOrder::getPaymentTime, lawyerConsultationOrderVO.getEndTimeNew() );
            }

            // 查询全部已支付订单的统计
            List<LawyerConsultationOrder> allPaidOrders = consultationOrderMapper.selectList(allRevenueWrapper);
            long allOrderCount = allPaidOrders.size();
            long allRevenue = allPaidOrders.stream()
                    .filter(order -> order.getOrderAmount() != null)
                    .mapToLong(LawyerConsultationOrder::getOrderAmount)
                    .sum();

            long consultationFee = allPaidOrders.stream()
                    .filter(order -> order.getConsultationFee() != null)
                    .mapToLong(LawyerConsultationOrder::getConsultationFee)
                    .sum();

            revenueVO.setAllOrderCount(allOrderCount);
            revenueVO.setAllRevenue(allRevenue-consultationFee);


            // 查询进行中订单的统计（orderStatus = 2 且已支付）
            LambdaQueryWrapper<LawyerConsultationOrder> inProgressWrapper = new LambdaQueryWrapper<>();
            inProgressWrapper.eq(LawyerConsultationOrder::getLawyerUserId, lawyerConsultationOrderVO.getLawyerUserId())
                    .eq(LawyerConsultationOrder::getOrderStatus, LawyerStatusEnum.INPROGRESS.getStatus()) // 2:进行中
                    .eq(LawyerConsultationOrder::getPaymentStatus, 1) // 已支付
                    .eq(LawyerConsultationOrder::getDeleteFlag, 0);
            
            // 添加时间段筛选条件（根据支付时间）
            if (lawyerConsultationOrderVO.getStartTimeNew() != null) {
                inProgressWrapper.ge(LawyerConsultationOrder::getPaymentTime, lawyerConsultationOrderVO.getStartTimeNew());
            }
            if (lawyerConsultationOrderVO.getEndTimeNew()  != null) {
                inProgressWrapper.le(LawyerConsultationOrder::getPaymentTime, lawyerConsultationOrderVO.getEndTimeNew() );
            }

            List<LawyerConsultationOrder> inProgressOrders = consultationOrderMapper.selectList(inProgressWrapper);
            long inProgressOrderCount = inProgressOrders.size();

            long inProgressRevenue = inProgressOrders.stream()
                    .filter(order -> order.getOrderAmount() != null)
                    .mapToLong(LawyerConsultationOrder::getOrderAmount)
                    .sum();

            long inProgressFee = inProgressOrders.stream()
                    .filter(order -> order.getConsultationFee() != null)
                    .mapToLong(LawyerConsultationOrder::getConsultationFee)
                    .sum();

            revenueVO.setInProgressOrderCount(inProgressOrderCount);
            revenueVO.setInProgressRevenue(inProgressRevenue-inProgressFee);


            // 查询已完成订单的统计（orderStatus = 3 且已支付）
            LambdaQueryWrapper<LawyerConsultationOrder> completedWrapper = new LambdaQueryWrapper<>();
            completedWrapper.eq(LawyerConsultationOrder::getLawyerUserId, lawyerConsultationOrderVO.getLawyerUserId())
                    .eq(LawyerConsultationOrder::getOrderStatus, LawyerStatusEnum.COMPLETE.getStatus()) // 3:已完成
                    .eq(LawyerConsultationOrder::getPaymentStatus, 1) // 已支付
                    .eq(LawyerConsultationOrder::getDeleteFlag, 0);
            
            // 添加时间段筛选条件（根据支付时间）
            if (lawyerConsultationOrderVO.getStartTimeNew() != null) {
                completedWrapper.ge(LawyerConsultationOrder::getPaymentTime, lawyerConsultationOrderVO.getStartTimeNew());
            }
            if (lawyerConsultationOrderVO.getEndTimeNew()  != null) {
                completedWrapper.le(LawyerConsultationOrder::getPaymentTime, lawyerConsultationOrderVO.getEndTimeNew() );
            }

            List<LawyerConsultationOrder> completedOrders = consultationOrderMapper.selectList(completedWrapper);
            long completedOrderCount = completedOrders.size();
            long completedRevenue = completedOrders.stream()
                    .filter(order -> order.getOrderAmount() != null)
                    .mapToLong(LawyerConsultationOrder::getOrderAmount)
                    .sum();

            long completedFee = completedOrders.stream()
                    .filter(order -> order.getConsultationFee() != null)
                    .mapToLong(LawyerConsultationOrder::getConsultationFee)
                    .sum();

            revenueVO.setCompletedOrderCount(completedOrderCount);
            revenueVO.setCompletedRevenue(completedRevenue-completedFee);

            // 构建返回结果
            Map<String, Object> allRevenueMap = new HashMap<>();
            allRevenueMap.put("name", "全部收益");
            allRevenueMap.put("orderCount", revenueVO.getAllOrderCount());
            allRevenueMap.put("totalRevenue", revenueVO.getAllRevenue());
            resultMap.put("allRevenue", allRevenueMap);

            Map<String, Object> inProgressMap = new HashMap<>();
            inProgressMap.put("name", "进行中");
            inProgressMap.put("orderCount", revenueVO.getInProgressOrderCount());
            inProgressMap.put("totalRevenue", revenueVO.getInProgressRevenue());
            resultMap.put("inProgress", inProgressMap);

            Map<String, Object> completedMap = new HashMap<>();
            completedMap.put("name", "已完成");
            completedMap.put("orderCount", revenueVO.getCompletedOrderCount());
            completedMap.put("totalRevenue", revenueVO.getCompletedRevenue());
            resultMap.put("completed", completedMap);

            log.info("查询订单收益成功，律师ID={}, 全部订单数={}, 全部收益={}, 进行中订单数={}, 进行中收益={}, 已完成订单数={}, 已完成收益={}",
                    lawyerConsultationOrderVO.getLawyerUserId(), allOrderCount, allRevenue, inProgressOrderCount, inProgressRevenue,
                    completedOrderCount, completedRevenue);

            return R.data(resultMap);

        } catch (Exception e) {
            log.error("查询订单收益失败，律师ID={}", lawyerConsultationOrderVO.getLawyerUserId(), e);
            return R.fail("查询订单收益失败：" + e.getMessage());
        }
    }

    /**
     * 用户申请退款
     * <p>
     * 申请退款前会进行以下校验和处理：
     * 1. 参数校验：用户ID和订单ID不能为空
     * 2. 订单存在性校验：订单必须存在
     * 3. 订单归属校验：订单必须属于该用户
     * 4. 订单状态校验：只有进行中(2)和已完成(3)状态的订单可以申请退款
     * 5. 退款状态校验：已申请退款的订单不允许重复申请
     * 6. 更新订单的申请退款状态为已申请(1)，并更新退款申请时间
     * </p>
     *
     * @param clientUserId 客户端用户ID
     * @param orderId      订单ID
     * @return 申请退款结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> applyRefund(String clientUserId, String orderId, String applyRefundReason) {
        log.info("开始申请退款，用户ID={}, 订单ID={}", clientUserId, orderId);

        // 1. 参数校验
        if (!StringUtils.hasText(clientUserId)) {
            log.warn("申请退款失败：用户ID为空或无效，clientUserId={}", clientUserId);
            return R.fail("用户ID不能为空");
        }

        if (!StringUtils.hasText(orderId)) {
            log.warn("申请退款失败：订单ID为空或无效，orderId={}", orderId);
            return R.fail("订单ID不能为空");
        }

        // 2. 查询订单信息
        LawyerConsultationOrder order = consultationOrderMapper.selectById(orderId);
        if (order == null) {
            log.warn("申请退款失败：订单不存在，订单ID={}", orderId);
            return R.fail("订单不存在");
        }

        // 3. 订单归属校验：订单必须属于该用户
        if (!clientUserId.equals(order.getClientUserId().toString())) {
            log.warn("申请退款失败：订单不属于该用户，订单ID={}, 订单用户ID={}, 请求用户ID={}",
                    orderId, order.getClientUserId(), clientUserId);
            return R.fail("订单不属于该用户，无法申请退款");
        }

        // 4. 订单状态校验：只有进行中(2)和已完成(3)状态的订单可以申请退款
        Integer orderStatus = order.getOrderStatus();
        Integer inProgressStatus = LawyerStatusEnum.INPROGRESS.getStatus(); // 2:进行中
        Integer completeStatus = LawyerStatusEnum.COMPLETE.getStatus(); // 3:已完成

        if (!inProgressStatus.equals(orderStatus) && !completeStatus.equals(orderStatus)) {
            log.warn("申请退款失败：订单状态不允许申请退款，订单ID={}, 订单编号={}, 订单状态={}",
                    orderId, order.getOrderNumber(), orderStatus);
            return R.fail("只有进行中或已完成的订单可以申请退款");
        }

        // 5. 退款状态校验：已申请退款的订单不允许重复申请
        String applyRefundStatus = order.getApplyRefundStatus();
        String appliedStatus = "1"; // 1:已申请
        String lawyerAgreedStatus = "3"; // 3:律师已同意
        if (appliedStatus.equals(applyRefundStatus) || lawyerAgreedStatus.equals(applyRefundStatus)) {
            log.warn("申请退款失败：订单已申请退款，不允许重复申请，订单ID={}, 订单编号={}, 退款状态={}",
                    orderId, order.getOrderNumber(), applyRefundStatus);
            return R.fail("订单已申请退款，不允许重复申请");
        }

        // 6. 更新订单的申请退款状态为已申请(1)，并更新退款申请时间
        LambdaUpdateWrapper<LawyerConsultationOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LawyerConsultationOrder::getId, orderId)
                .set(LawyerConsultationOrder::getApplyRefundStatus, appliedStatus)
                .set(LawyerConsultationOrder::getApplyRefundTime, new Date())
                .set(LawyerConsultationOrder::getUpdatedTime, new Date()).set(LawyerConsultationOrder::getApplyRefundReason, applyRefundReason);

        int updateCount = consultationOrderMapper.update(null, updateWrapper);
        boolean success = updateCount > 0;

        // 7. 记录操作结果并发送通知
        if (success) {
            //设置订单超时退款时间
            orderExpirationService.setOrderRefundTimeout(order.getOrderNumber(), 60 * Long.parseLong(coefficients));

            log.info("申请退款成功，订单ID={}, 订单编号={}, 订单状态={}, 退款状态=已申请",
                    orderId, order.getOrderNumber(), orderStatus);
            
            // 发送退款申请通知给申请人
            sendRefundApplyNotice(order, clientUserId);
            
            return R.data(true, "退款申请已提交，请等待律师处理");
        } else {
            log.error("申请退款失败：更新数据库失败，订单ID={}, 订单编号={}", orderId, order.getOrderNumber());
            return R.fail("申请退款失败，请稍后重试");
        }
    }

    /**
     * 用户端完成订单
     * <p>
     * 完成订单前会进行以下校验和处理：
     * 1. 参数校验：用户ID和订单ID不能为空
     * 2. 订单存在性校验：订单必须存在
     * 3. 订单归属校验：订单必须属于该用户
     * 4. 订单状态校验：只有进行中(2)状态的订单可以完成
     * 5. 更新订单状态为已完成(3)，并更新完成时间
     * </p>
     *
     * @param clientUserId 客户端用户ID
     * @param orderId      订单ID
     * @return 完成订单结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> completeOrder(String clientUserId, String orderId) {
        log.info("开始完成订单，用户ID={}, 订单ID={}", clientUserId, orderId);

        // 1. 参数校验
        if (StringUtils.isEmpty(clientUserId)) {
            log.warn("完成订单失败：用户ID为空或无效，clientUserId={}", clientUserId);
            return R.fail("用户ID不能为空");
        }

        if (StringUtils.isEmpty(orderId)) {
            log.warn("完成订单失败：订单ID为空或无效，orderId={}", orderId);
            return R.fail("订单ID不能为空");
        }

        // 2. 查询订单信息
        LawyerConsultationOrder order = consultationOrderMapper.selectById(orderId);
        if (order == null) {
            log.warn("完成订单失败：订单不存在，订单ID={}", orderId);
            return R.fail("订单不存在");
        }

        // 3. 订单归属校验：订单必须属于该用户
        if (!clientUserId.equals(order.getClientUserId().toString())) {
            log.warn("完成订单失败：订单不属于该用户，订单ID={}, 订单用户ID={}, 请求用户ID={}",
                    orderId, order.getClientUserId(), clientUserId);
            return R.fail("订单不属于该用户，无法完成订单");
        }

        // 4. 订单状态校验：只有进行中(2)状态的订单可以完成
        Integer orderStatus = order.getOrderStatus();
        Integer inProgressStatus = LawyerStatusEnum.INPROGRESS.getStatus(); // 2:进行中
        Integer completeStatus = LawyerStatusEnum.COMPLETE.getStatus(); // 3:已完成

        if (!inProgressStatus.equals(orderStatus)) {
            log.warn("完成订单失败：订单状态不允许完成，订单ID={}, 订单编号={}, 订单状态={}",
                    orderId, order.getOrderNumber(), orderStatus);
            return R.fail("只有进行中的订单可以完成");
        }

        // 5. 更新订单状态为已完成(3)，并更新咨询结束时间和更新时间
        LambdaUpdateWrapper<LawyerConsultationOrder> updateWrapper = new LambdaUpdateWrapper<>();
        Date now = new Date();
        updateWrapper.eq(LawyerConsultationOrder::getId, orderId)
                .set(LawyerConsultationOrder::getOrderStatus, completeStatus)
                .set(LawyerConsultationOrder::getEndTime, now)
                .set(LawyerConsultationOrder::getUpdatedTime, now);

        int updateCount = consultationOrderMapper.update(null, updateWrapper);
        boolean success = updateCount > 0;

        // 6. 记录操作结果
        if (success) {
            log.info("完成订单成功，订单ID={}, 订单编号={}, 原状态={}, 新状态=已完成",
                    orderId, order.getOrderNumber(), orderStatus);
            return R.data(true, "订单已完成");
        } else {
            log.error("完成订单失败：更新数据库失败，订单ID={}, 订单编号={}", orderId, order.getOrderNumber());
            return R.fail("完成订单失败，请稍后重试");
        }
    }

    /**
     * 获取申请退款订单详情
     * <p>
     * 根据订单ID查询订单信息，用于退款申请详情展示
     * </p>
     *
     * @param orderId 订单ID，不能为空
     * @return 订单信息，如果订单ID为空或订单不存在则返回null
     */
    @Override
    public LawyerConsultationOrder getApplyRefundDetail(String orderId) {
        log.info("开始查询申请退款订单详情，订单ID={}", orderId);

        // 参数校验：订单ID不能为空
        if (!StringUtils.hasText(orderId)) {
            log.warn("查询申请退款订单详情失败：订单ID为空");
            return null;
        }

        try {
            // 查询订单信息
            LawyerConsultationOrder order = consultationOrderMapper.selectById(orderId);
            if (order == null) {
                log.warn("查询申请退款订单详情失败：订单不存在，订单ID={}", orderId);
                return null;
            }

            log.info("查询申请退款订单详情成功，订单ID={}, 订单编号={}", orderId, order.getOrderNumber());
            return order;
        } catch (Exception e) {
            log.error("查询申请退款订单详情异常，订单ID={}, 异常信息={}", orderId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 格式化收益金额（分转元）
     *
     * @param revenueInCents 收益金额（单位：分）
     * @return 格式化后的金额字符串（单位：元）
     */
    private String formatRevenue(long revenueInCents) {
        if (revenueInCents == 0) {
            return "0";
        }
        BigDecimal revenue = new BigDecimal(revenueInCents);
        BigDecimal revenueInYuan = revenue.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
        return revenueInYuan.toString();
    }

    /**
     * 发送退款申请通知给申请人
     *
     * @param order        订单对象
     * @param clientUserId 客户端用户ID
     */
    private void sendRefundApplyNotice(LawyerConsultationOrder order, String clientUserId) {
        try {
            LifeNotice lifeNotice = createRefundApplyNotice(order, clientUserId);
            if (lifeNotice == null) {
                log.warn("生成退款申请通知失败，订单ID={}, 用户ID={}", order.getId(), clientUserId);
                return;
            }

            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            int noticeResult = lifeNoticeMapper.insert(lifeNotice);
            if (noticeResult <= 0) {
                log.warn("保存退款申请通知失败，订单ID={}, 用户ID={}", order.getId(), clientUserId);
                return;
            }

            // 发送WebSocket消息
            WebSocketVo webSocketVo = buildWebSocketVo(lifeNotice);
            webSocketProcess.sendMessage(lifeNotice.getReceiverId(),
                    JSONObject.from(webSocketVo).toJSONString());

            log.info("退款申请通知发送成功，接收人ID={}, 订单编号={}", lifeNotice.getReceiverId(), order.getOrderNumber());

        } catch (Exception e) {
            log.error("发送退款申请通知异常，订单ID={}, 用户ID={}, 异常信息={}",
                    order.getId(), clientUserId, e.getMessage(), e);
        }
    }

    /**
     * 创建退款申请通知对象
     *
     * @param order        订单对象
     * @param clientUserId 客户端用户ID
     * @return 通知对象，如果生成失败返回null
     */
    private LifeNotice createRefundApplyNotice(LawyerConsultationOrder order, String clientUserId) {
        if (order == null || clientUserId == null) {
            log.warn("创建退款申请通知失败，订单或用户ID为空");
            return null;
        }

        try {
            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setSenderId(SYSTEM_SENDER_ID);
            lifeNotice.setBusinessId(order.getId());
            lifeNotice.setTitle("申请退款通知");

            // 获取申请人接收ID
            String receiverId = getClientReceiverId(clientUserId);
            if (org.apache.commons.lang3.StringUtils.isEmpty(receiverId)) {
                log.warn("获取申请人接收ID失败，用户ID={}", clientUserId);
                return null;
            }
            lifeNotice.setReceiverId(receiverId);

            // 构建通知消息内容
            String orderNumber = order.getOrderNumber();
            String message = String.format("您的编号为%s的订单，申请退款的信息已提交给律师，等待律师同意。律师同意或48小时未处理，系统会将订单金额原路返还，请注意查收。", 
                    orderNumber != null ? orderNumber : "");

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("title", "申请退款通知");
            jsonObject.put("message", message);
            lifeNotice.setContext(jsonObject.toJSONString());
            lifeNotice.setNoticeType(1);
            lifeNotice.setBusinessType(1);

            return lifeNotice;

        } catch (Exception e) {
            log.error("创建退款申请通知异常，订单ID={}, 用户ID={}, 异常信息={}",
                    order.getId(), clientUserId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取客户端用户接收ID
     *
     * @param clientUserId 客户端用户ID
     * @return 接收人ID，格式：user_ + 手机号
     */
    private String getClientReceiverId(String clientUserId) {
        try {
            LifeUser lifeUser = lifeUserMapper.selectById(clientUserId);
            if (lifeUser != null && org.apache.commons.lang3.StringUtils.isNotEmpty(lifeUser.getUserPhone())) {
                return "user_" + lifeUser.getUserPhone();
            }
        } catch (Exception e) {
            log.error("获取客户端用户手机号异常，用户ID={}, 异常信息={}", clientUserId, e.getMessage(), e);
        }

        log.warn("获取客户端用户手机号失败，用户ID={}", clientUserId);
        return null;
    }

    /**
     * 构建WebSocket消息对象
     *
     * @param lifeNotice 通知对象
     * @return WebSocketVo对象
     */
    private WebSocketVo buildWebSocketVo(LifeNotice lifeNotice) {
        WebSocketVo webSocketVo = new WebSocketVo();
        webSocketVo.setSenderId(SYSTEM_SENDER_ID);
        webSocketVo.setReceiverId(lifeNotice.getReceiverId());
        webSocketVo.setCategory("notice");
        webSocketVo.setNoticeType("1");
        webSocketVo.setIsRead(0);
        webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
        return webSocketVo;
    }

    /**
     * 为订单列表设置订单价格字符串
     * <p>
     * 遍历订单列表，为每个订单设置orderPriceStr字段
     * </p>
     *
     * @param voPage 订单列表分页对象
     */
    private void setOrderPriceStrForOrderList(IPage<LawyerConsultationOrderVO> voPage) {
        if (voPage == null || CollectionUtils.isEmpty(voPage.getRecords())) {
            return;
        }

        for (LawyerConsultationOrderVO orderVO : voPage.getRecords()) {
            setOrderPriceStr(orderVO);
        }
    }

    /**
     * 设置订单价格字符串
     * <p>
     * 根据charge_minute、minute_num、charge_time、time_num字段设置orderPriceStr
     * 优先级：charge_minute和minute_num > charge_time和time_num
     * chargeMinute和chargeTime单位都是分，需要转换为元并保留两位小数，去掉尾随的0
     * </p>
     * <p>
     * 处理逻辑：
     * 1. 优先检查是否按分钟收费（chargeMinute和minuteNum都不为空）
     * 2. 其次检查是否按次数收费（chargeTime和timeNum都不为空）
     * 3. 如果都不满足，则设置为空字符串
     * </p>
     *
     * @param orderVO 订单VO对象，不能为null
     */
    private void setOrderPriceStr(LawyerConsultationOrderVO orderVO) {
        if (orderVO == null) {
            log.warn("设置订单价格字符串失败：订单VO对象为null");
            return;
        }

        try {
            // 优先处理按分钟收费
            if (isMinuteBasedCharging(orderVO)) {
                String orderPriceStr = buildMinuteBasedPriceStr(orderVO);
                orderVO.setOrderPriceStr(orderPriceStr);
                log.debug("设置订单价格字符串成功（按分钟收费），chargeMinute={}, minuteNum={}, orderPriceStr={}",
                        orderVO.getChargeMinute(), orderVO.getMinuteNum(), orderPriceStr);
                return;
            }

            // 其次处理按次数收费
            if (isTimeBasedCharging(orderVO)) {
                String orderPriceStr = buildTimeBasedPriceStr(orderVO);
                orderVO.setOrderPriceStr(orderPriceStr);
                log.debug("设置订单价格字符串成功（按次数收费），chargeTime={}, timeNum={}, orderPriceStr={}",
                        orderVO.getChargeTime(), orderVO.getTimeNum(), orderPriceStr);
                return;
            }

            // 当都为空则返回空
            orderVO.setOrderPriceStr(DEFAULT_PRICE_STR);
            log.debug("订单价格字段都为空，设置默认空字符串");

        } catch (Exception e) {
            log.error("设置订单价格字符串异常，异常信息：{}", e.getMessage(), e);
            // 异常时设置默认值，避免影响主流程
            orderVO.setOrderPriceStr(DEFAULT_PRICE_STR);
        }
    }

    /**
     * 判断是否按分钟收费
     * <p>
     * 通过检查chargeMinute和minuteNum是否都不为空来判断
     * </p>
     *
     * @param orderVO 订单VO对象
     * @return true表示按分钟收费，false表示不是
     */
    private boolean isMinuteBasedCharging(LawyerConsultationOrderVO orderVO) {
        return orderVO != null
                && orderVO.getChargeMinute() != null
                && orderVO.getMinuteNum() != null;
    }

    /**
     * 判断是否按次数收费
     * <p>
     * 通过检查chargeTime和timeNum是否都不为空来判断
     * </p>
     *
     * @param orderVO 订单VO对象
     * @return true表示按次数收费，false表示不是
     */
    private boolean isTimeBasedCharging(LawyerConsultationOrderVO orderVO) {
        return orderVO != null
                && orderVO.getChargeTime() != null
                && orderVO.getTimeNum() != null;
    }

    /**
     * 构建按分钟收费的价格字符串
     * <p>
     * 格式：￥{价格}/{分钟数}分钟
     * 例如：￥1.5/30分钟
     * </p>
     *
     * @param orderVO 订单VO对象
     * @return 格式化后的价格字符串
     */
    private String buildMinuteBasedPriceStr(LawyerConsultationOrderVO orderVO) {
        // chargeMinute单位是分，需要转换为元并保留两位小数，去掉尾随的0
        BigDecimal chargeMinuteYuan = convertFenToYuan(orderVO.getChargeMinute());
        String priceStr = formatPrice(chargeMinuteYuan);
        return String.format(PRICE_FORMAT_MINUTE, priceStr, orderVO.getMinuteNum());
    }

    /**
     * 构建按次数收费的价格字符串
     * <p>
     * 格式：￥{价格}/{次数}次
     * 例如：￥5/3次
     * </p>
     *
     * @param orderVO 订单VO对象
     * @return 格式化后的价格字符串
     */
    private String buildTimeBasedPriceStr(LawyerConsultationOrderVO orderVO) {
        // chargeTime单位是分，需要转换为元并保留两位小数，去掉尾随的0
        BigDecimal chargeTimeYuan = convertFenToYuan(orderVO.getChargeTime());
        String priceStr = formatPrice(chargeTimeYuan);
        return String.format(PRICE_FORMAT_TIME, priceStr, orderVO.getTimeNum());
    }

    /**
     * 将分转换为元
     * <p>
     * 分转元，保留指定小数位数，使用四舍五入
     * </p>
     *
     * @param fen 金额（分），单位：分
     * @return 金额（元），单位：元，保留2位小数
     */
    private BigDecimal convertFenToYuan(Integer fen) {
        if (fen == null) {
            log.warn("转换分转元失败：金额为null，返回0");
            return BigDecimal.ZERO;
        }

        if (fen < 0) {
            log.warn("转换分转元失败：金额为负数，fen={}，返回0", fen);
            return BigDecimal.ZERO;
        }

        return BigDecimal.valueOf(fen)
                .divide(BigDecimal.valueOf(FEN_TO_YUAN), DECIMAL_SCALE, RoundingMode.HALF_UP);
    }

    /**
     * 格式化价格，去掉尾随的0
     * <p>
     * 将BigDecimal价格格式化为字符串，去掉尾随的0
     * 例如：1.00 -> 1, 1.50 -> 1.5, 1.25 -> 1.25
     * </p>
     *
     * @param price 价格（BigDecimal），可能为null
     * @return 格式化后的价格字符串，如果price为null则返回"0"
     */
    private String formatPrice(BigDecimal price) {
        if (price == null) {
            log.debug("格式化价格：价格为null，返回默认值0");
            return DEFAULT_FORMATTED_PRICE;
        }

        try {
            // 去掉尾随的0
            String formattedPrice = price.stripTrailingZeros().toPlainString();
            log.debug("格式化价格成功，原始价格={}, 格式化后={}", price, formattedPrice);
            return formattedPrice;
        } catch (Exception e) {
            log.error("格式化价格异常，price={}，异常信息：{}", price, e.getMessage(), e);
            // 异常时返回默认值
            return DEFAULT_FORMATTED_PRICE;
        }
    }

    /**
     * 设置订单列表的评价状态（commonStatus）
     * <p>
     * 根据订单ID查询 lawyer_order_review 和 comment_appeals 表，设置每个订单的评价状态：
     * 1. 如果 lawyer_order_review 表中 order_id=订单ID 的记录不存在，则 commonStatus=1
     * 2. 如果 lawyer_order_review 存在，但 comment_appeals 表中 comment_id=lawyer_order_review.id 的记录不存在，
     *    或者存在但 processing_status(status) 为 0 或 1，则 commonStatus=2
     * 3. 其他情况 commonStatus=3
     * </p>
     *
     * @param voPage 订单分页对象
     */
    private void setCommonStatusForOrderList(IPage<LawyerConsultationOrderVO> voPage) {
        if (voPage == null || CollectionUtils.isEmpty(voPage.getRecords())) {
            log.debug("订单列表为空，跳过设置评价状态");
            return;
        }

        // 提取订单ID列表
        List<Integer> orderIds = voPage.getRecords().stream()
                .map(LawyerConsultationOrderVO::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(orderIds)) {
            log.debug("订单ID列表为空，跳过设置评价状态");
            return;
        }

        // 查询 lawyer_order_review 表，order_id=订单ID
        Map<Integer, OrderReview> orderIdToReviewMap = queryOrderReviewByOrderIds(orderIds);

        // 提取 lawyer_order_review 的 ID 列表
        List<Integer> reviewIds = orderIdToReviewMap.values().stream()
                .filter(Objects::nonNull)
                .map(OrderReview::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 查询 comment_appeals 表，comment_id=lawyer_order_review.id
        Map<Integer, CommentAppeal> reviewIdToAppealMap = queryCommentAppealsByReviewIds(reviewIds);

        // 直接根据订单ID查询申诉记录（包括已删除评论对应的申诉）
        Map<Integer, CommentAppeal> orderIdToAppealMap = queryCommentAppealsByOrderIds(orderIds);

        // 为每个订单设置 commonStatus 和 canCommentAgain
        for (LawyerConsultationOrderVO orderVO : voPage.getRecords()) {
            if (orderVO == null || orderVO.getId() == null) {
                continue;
            }

            String commonStatus = calculateCommonStatus(
                    orderVO.getId(), orderIdToReviewMap, reviewIdToAppealMap);
            orderVO.setCommonStatus(commonStatus);

            // 判断是否允许再次评论
            // 规则：
            // 1. 如果订单已经有评价（评价存在且未删除），不允许再次评论
            // 2. 如果订单没有评价，但有申诉记录且申诉状态为1（已通过），说明评论被举报且举报通过（评论被删除），不允许再次评论
            // 3. 其他情况，允许评论
            OrderReview existingReview = orderIdToReviewMap.get(orderVO.getId());
            CommentAppeal appeal = orderIdToAppealMap.get(orderVO.getId());
            
            if (existingReview != null) {
                // 订单已经有评价（评价存在且未删除），不允许再次评论
                orderVO.setCanCommentAgain(false);
                log.debug("订单已有评价，不允许再次评论，orderId={}, reviewId={}", 
                        orderVO.getId(), existingReview.getId());
            } else if (appeal != null && appeal.getStatus() != null && appeal.getStatus() == 1) {
                // 订单没有评价，但有申诉记录且申诉状态为1（已通过），说明评论被举报且举报通过（评论被删除），不允许再次评论
                orderVO.setCanCommentAgain(false);
                log.debug("订单评论被举报且举报通过，不允许再次评论，orderId={}, appealStatus={}", 
                        orderVO.getId(), appeal.getStatus());
            } else {
                // 其他情况（没有评价且没有申诉记录，或申诉未通过），允许评论
                orderVO.setCanCommentAgain(true);
            }
        }

        log.debug("设置订单评价状态完成，订单数量={}", voPage.getRecords().size());
    }

    /**
     * 根据订单ID列表查询 lawyer_order_review 记录
     * <p>
     * 查询条件：order_id=订单ID
     * 如果一个 order_id 存在多条记录，只取最新的一条（按创建时间倒序）
     * </p>
     *
     * @param orderIds 订单ID列表
     * @return 订单ID到评价记录的映射，key为订单ID，value为评价记录（每个订单ID对应最新的一条评价）
     */
    private Map<Integer, OrderReview> queryOrderReviewByOrderIds(List<Integer> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return Collections.emptyMap();
        }

        try {
            LambdaQueryWrapper<OrderReview> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(OrderReview::getOrderId, orderIds)
                    .eq(OrderReview::getDeleteFlag, 0)
                    .orderByDesc(OrderReview::getCreatedTime);

            List<OrderReview> reviewList = orderReviewMapper.selectList(queryWrapper);

            // 按 orderId 分组，每个 orderId 只保留最新的一条记录
            // 由于查询已按创建时间倒序排序，同一个 orderId 的第一条记录即为最新的
            return reviewList.stream()
                    .filter(Objects::nonNull)
                    .filter(review -> review.getId() != null && review.getOrderId() != null)
                    .collect(Collectors.toMap(
                            OrderReview::getOrderId,
                            review -> review,
                            (existing, replacement) -> {
                                // 由于已按创建时间倒序排序，existing 是先遍历到的记录（即最新的）
                                // 但为了安全起见，仍然比较创建时间，确保保留最新的记录
                                if (existing.getCreatedTime() != null && replacement.getCreatedTime() != null) {
                                    // existing.getCreatedTime() >= replacement.getCreatedTime()（因为已排序）
                                    return existing.getCreatedTime().after(replacement.getCreatedTime()) 
                                            || existing.getCreatedTime().equals(replacement.getCreatedTime())
                                            ? existing 
                                            : replacement;
                                } else if (existing.getCreatedTime() != null) {
                                    // existing 有创建时间，replacement 没有，保留 existing
                                    return existing;
                                } else if (replacement.getCreatedTime() != null) {
                                    // replacement 有创建时间，existing 没有，保留 replacement
                                    return replacement;
                                } else {
                                    // 都没有创建时间，保留已存在的记录（先遍历到的，即排序后的第一条）
                                    return existing;
                                }
                            }
                    ));
        } catch (Exception e) {
            log.error("查询 lawyer_order_review 记录异常，orderIds={}，异常信息：{}", orderIds, e.getMessage(), e);
            return Collections.emptyMap();
        }
    }

    /**
     * 根据评价ID列表查询 comment_appeals 记录
     * <p>
     * 查询条件：comment_id=评价ID（lawyer_order_review.id）
     * </p>
     *
     * @param reviewIds 评价ID列表（lawyer_order_review.id）
     * @return 评价ID到申诉记录的映射，key为评价ID，value为申诉记录
     */
    private Map<Integer, CommentAppeal> queryCommentAppealsByReviewIds(List<Integer> reviewIds) {
        if (CollectionUtils.isEmpty(reviewIds)) {
            return Collections.emptyMap();
        }

        try {
            // 构建查询条件
            LambdaQueryWrapper<CommentAppeal> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(CommentAppeal::getCommentId, reviewIds)
                    .eq(CommentAppeal::getDeleteFlag, DELETE_FLAG_NOT_DELETED);

            List<CommentAppeal> appealList = commentAppealMapper.selectList(queryWrapper);

            // 构建映射：key为评价ID，value为申诉记录
            // 如果一个评价有多个申诉记录，只取第一个（通常一个评价应该只有一个申诉记录）
            Map<Integer, CommentAppeal> resultMap = new HashMap<>();

            for (CommentAppeal appeal : appealList) {
                if (appeal == null || appeal.getCommentId() == null) {
                    continue;
                }

                // 如果已经存在该评价的申诉记录，保留第一个（先查询到的）
                if (!resultMap.containsKey(appeal.getCommentId())) {
                    resultMap.put(appeal.getCommentId(), appeal);
                }
            }

            log.debug("查询 comment_appeals 记录成功，reviewIds={}，查询到记录数={}",
                    reviewIds, resultMap.size());

            return resultMap;
        } catch (Exception e) {
            log.error("查询 comment_appeals 记录异常，reviewIds={}，异常信息：{}",
                    reviewIds, e.getMessage(), e);
            return Collections.emptyMap();
        }
    }

    /**
     * 根据订单ID列表查询 comment_appeals 记录
     * <p>
     * 查询条件：order_id=订单ID
     * 用于判断订单是否曾经有评论被申诉且申诉通过（评论被删除）
     * </p>
     *
     * @param orderIds 订单ID列表
     * @return 订单ID到申诉记录的映射，key为订单ID，value为申诉记录
     */
    private Map<Integer, CommentAppeal> queryCommentAppealsByOrderIds(List<Integer> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return Collections.emptyMap();
        }

        try {
            // 构建查询条件
            LambdaQueryWrapper<CommentAppeal> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(CommentAppeal::getOrderId, orderIds)
                    .eq(CommentAppeal::getDeleteFlag, DELETE_FLAG_NOT_DELETED);

            List<CommentAppeal> appealList = commentAppealMapper.selectList(queryWrapper);

            // 构建映射：key为订单ID，value为申诉记录
            // 如果一个订单有多个申诉记录，只取第一个（通常一个订单应该只有一个申诉记录）
            Map<Integer, CommentAppeal> resultMap = new HashMap<>();

            for (CommentAppeal appeal : appealList) {
                if (appeal == null || appeal.getOrderId() == null) {
                    continue;
                }

                // 如果已经存在该订单的申诉记录，保留第一个（先查询到的）
                if (!resultMap.containsKey(appeal.getOrderId())) {
                    resultMap.put(appeal.getOrderId(), appeal);
                }
            }

            log.debug("根据订单ID查询 comment_appeals 记录成功，orderIds={}，查询到记录数={}",
                    orderIds, resultMap.size());

            return resultMap;
        } catch (Exception e) {
            log.error("根据订单ID查询 comment_appeals 记录异常，orderIds={}，异常信息：{}",
                    orderIds, e.getMessage(), e);
            return Collections.emptyMap();
        }
    }

    /**
     * 计算订单的评价状态
     * <p>
     * 根据查询结果计算订单的 commonStatus 值：
     * 1. 如果 lawyer_order_review 表中没有记录，则 commonStatus=1
     * 2. 如果 comment_appeals 表中没有记录，或者 processing_status(status) 为 0 或 1，则 commonStatus=2
     * 3. 其他情况 commonStatus=3
     * </p>
     *
     * @param orderId               订单ID
     * @param orderIdToReviewMap    订单ID到评价记录的映射
     * @param reviewIdToAppealMap   评价ID到申诉记录的映射
     * @return 评价状态字符串（"1"、"2"或"3"）
     */
    private String calculateCommonStatus(Integer orderId,
                                        Map<Integer, OrderReview> orderIdToReviewMap,
                                        Map<Integer, CommentAppeal> reviewIdToAppealMap) {
        // 第一步：查询 lawyer_order_review 表
        OrderReview review = orderIdToReviewMap.get(orderId);

        // 如果关联不出来记录，则 commonStatus=1
        if (review == null || review.getId() == null) {
            log.debug("订单未找到评价记录，设置 commonStatus=1，orderId={}", orderId);
            return "1";
        }

        // 第二步：查询 comment_appeals 表
        CommentAppeal appeal = reviewIdToAppealMap.get(review.getId());

        // 如果关联不出来或者关联出来的 processing_status(status) 为 0 或者 1，则 commonStatus=2
        if (appeal == null) {
            log.debug("评价未找到申诉记录，设置 commonStatus=2，orderId={}, reviewId={}",
                    orderId, review.getId());
            return "2";
        }

        Integer status = appeal.getStatus();
        if (status == null || status == 0 || status == 2) {
            log.debug("申诉记录处理状态为0或1，设置 commonStatus=2，orderId={}, reviewId={}, status={}",
                    orderId, review.getId(), status);
            return "2";
        }

        // 其他情况 commonStatus=3
        log.debug("设置 commonStatus=3，orderId={}, reviewId={}, status={}",
                orderId, review.getId(), status);
        return "3";
    }


}

