package shop.alien.lawyer.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.LawyerUserViolationDto;
import shop.alien.entity.store.vo.LawyerUserViolationVo;
import shop.alien.entity.store.vo.LawyerViolationDetailVO;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.mapper.*;
import shop.alien.lawyer.config.WebSocketProcess;
import shop.alien.lawyer.service.LawyerUserViolationService;
import shop.alien.lawyer.service.LawyerUserService;
import shop.alien.lawyer.util.ali.AliApi;
import shop.alien.util.common.EnumUtil;
import shop.alien.util.common.constant.LawyerStatusEnum;
import shop.alien.util.type.LifeNoticeUtil;

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

/**
 * <p>
 * 律师用户举报 服务实现类
 * </p>
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LawyerUserViolationServiceImpl extends ServiceImpl<LawyerUserViolationMapper, LawyerUserViolation> implements LawyerUserViolationService {

    /**
     * 用户类型：商户用户
     */
    private static final String USER_TYPE_STORE = "1";

    /**
     * 用户类型：普通用户
     */
    private static final String USER_TYPE_LIFE = "2";

    /**
     * 用户类型：律师用户
     */
    private static final String USER_TYPE_LAWYER = "3";

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

    /**
     * 日期时间格式
     */
    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 默认违规原因
     */
    private static final String DEFAULT_VIOLATION_REASON = "其他原因";

    /**
     * 默认通知消息
     */
    private static final String DEFAULT_NOTICE_MESSAGE = "平台已受理，感谢您的反馈！";

    /**
     * 处理状态：通过
     */
    private static final String PROCESSING_STATUS_APPROVED = "1";

    /**
     * 举报内容类型：订单举报
     */
    private static final String REPORT_CONTEXT_TYPE_ORDER = "6";

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

    /**
     * 图片分隔符
     */
    private static final String IMAGE_SEPARATOR = ",";

    /**
     * 最大分页大小
     */
    private static final int MAX_PAGE_SIZE = 100;

    private final LawyerUserViolationMapper lawyerUserViolationMapper;

    private final LawyerUserMapper lawyerUserMapper;

    private final StoreUserMapper storeUserMapper;

    private final LifeUserMapper lifeUserMapper;

    private final LawyerUserService lawyerUserService;

    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeNoticeUtil lifeNoticeUtil;

    private final WebSocketProcess webSocketProcess;

    private final StoreDictionaryMapper storeDictionaryMapper;

    private final LawyerConsultationOrderMapper consultationOrderMapper;

    private final AliApi aliApi;


    /**
     * 用户举报处理
     * <p>
     * 处理用户举报信息，包括：
     * 1. 参数校验
     * 2. 查询订单信息并设置举报人和被举报人ID
     * 3. 检查订单是否已被举报（一笔订单只能举报一次）
     * 4. 保存举报记录到数据库
     * 5. 向举报人发送受理通知
     * </p>
     *
     * @param lawyerUserViolation 举报信息对象，不能为null
     * @return 插入成功的记录数，失败返回0
     * @throws RuntimeException 当数据库操作失败或业务逻辑处理异常时抛出
     * @author system
     * @since 2025-01-XX
     */
    @Override
    public int userReporting(LawyerUserViolation lawyerUserViolation) {
        // 参数校验
        validateReportingParams(lawyerUserViolation);

        String orderNumber = lawyerUserViolation.getOrderNumber();
        
        // 查询订单信息并设置举报人和被举报人ID
        LawyerConsultationOrder consultationOrder = queryAndSetUserIds(lawyerUserViolation, orderNumber);
        if (consultationOrder == null) {
            log.warn("订单不存在或已删除，订单号：{}", orderNumber);
            return 0;
        }

        try {
            // 检查订单是否已被举报（一笔订单只能举报一次）
            boolean hasReported = checkOrderAlreadyReported(orderNumber);
            if (hasReported) {
                log.warn("订单已被举报，订单号：{}", orderNumber);
                throw new RuntimeException("该订单已被举报，无法重复举报");
            }

            // 保存举报记录
            int result = saveViolationRecord(lawyerUserViolation, consultationOrder);
            if (result <= 0) {
                return 0;
            }

            log.info("用户举报记录保存成功，举报ID：{}", lawyerUserViolation.getId());

            // 向举报人发送受理通知
            sendReportNoticeToReporter(lawyerUserViolation);

            log.info("用户举报处理完成，举报ID：{}", lawyerUserViolation.getId());
            return result;

        } catch (RuntimeException e) {
            log.error("用户举报处理业务异常，订单号：{}，异常信息：{}", orderNumber, e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("用户举报处理异常，订单号：{}，异常信息：{}", orderNumber, e.getMessage(), e);
            throw new RuntimeException("用户举报处理失败：" + e.getMessage(), e);
        }
    }

    /**
     * 校验举报参数
     *
     * @param lawyerUserViolation 举报信息对象
     * @throws RuntimeException 当参数无效时抛出
     */
    private void validateReportingParams(LawyerUserViolation lawyerUserViolation) {
        if (lawyerUserViolation == null) {
            log.warn("用户举报参数为空");
            throw new RuntimeException("举报信息不能为空");
        }

        String orderNumber = lawyerUserViolation.getOrderNumber();
        if (StringUtils.isEmpty(orderNumber)) {
            log.warn("用户举报订单号为空");
            throw new RuntimeException("订单号不能为空");
        }
    }

    /**
     * 查询订单信息并设置举报人和被举报人ID
     *
     * @param lawyerUserViolation 举报信息对象
     * @param orderNumber         订单号
     * @return 咨询订单对象，如果订单不存在返回null
     */
    private LawyerConsultationOrder queryAndSetUserIds(LawyerUserViolation lawyerUserViolation, String orderNumber) {
        LambdaQueryWrapper<LawyerConsultationOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LawyerConsultationOrder::getOrderNumber, orderNumber)
                .eq(LawyerConsultationOrder::getDeleteFlag, 0)
                .last("LIMIT 1");

        List<LawyerConsultationOrder> orderList = consultationOrderMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(orderList)) {
            return null;
        }

        LawyerConsultationOrder consultationOrder = orderList.get(0);
        // 设置被举报人ID（律师用户ID）
        if (consultationOrder.getLawyerUserId() != null) {
            lawyerUserViolation.setReportedUserId(consultationOrder.getLawyerUserId().toString());
            lawyerUserViolation.setReportedUserType("3");
        }
        // 设置举报人ID（客户用户ID）
        if (consultationOrder.getClientUserId() != null) {
            lawyerUserViolation.setReportingUserId(consultationOrder.getClientUserId().toString());
            lawyerUserViolation.setReportingUserType("2");

        }

        return consultationOrder;
    }

    /**
     * 保存举报记录
     *
     * @param lawyerUserViolation 举报信息对象
     * @param consultationOrder   咨询订单对象
     * @return 插入成功的记录数，失败返回0
     */
    private int saveViolationRecord(LawyerUserViolation lawyerUserViolation, LawyerConsultationOrder consultationOrder) {
        int result = lawyerUserViolationMapper.insert(lawyerUserViolation);
        if (result <= 0) {
            log.warn("用户举报记录保存失败，被举报用户ID：{}，举报用户ID：{}",
                    consultationOrder.getLawyerUserId(), consultationOrder.getClientUserId());
        }
        return result;
    }

    /**
     * 检查订单是否已被举报
     * <p>
     * 根据订单ID查询是否已存在举报记录（一笔订单只能举报一次）
     * </p>
     *
     * @param orderNumber 订单号
     * @return true-已举报，false-未举报
     */
    private boolean checkOrderAlreadyReported(String orderNumber) {
        if (StringUtils.isEmpty(orderNumber)) {
            return false;
        }

        try {
            LambdaQueryWrapper<LawyerUserViolation> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(LawyerUserViolation::getOrderNumber, orderNumber).eq(LawyerUserViolation::getDeleteFlag, 0)
                    .last("LIMIT 1");

            LawyerUserViolation existingReport = lawyerUserViolationMapper.selectOne(queryWrapper);
            return existingReport != null;
        } catch (Exception e) {
            log.error("检查订单举报状态异常，订单号：{}，异常信息：{}",
                    orderNumber, e.getMessage(), e);
            // 查询异常时，为了安全起见，返回true，阻止重复举报
            return true;
        }
    }

    /**
     * 向举报人发送受理通知
     *
     * @param lawyerUserViolation 举报信息对象
     */
    private void sendReportNoticeToReporter(LawyerUserViolation lawyerUserViolation) {
        try {
            LifeNotice lifeNotice = getLifeNotice(lawyerUserViolation);
            if (lifeNotice == null) {
                log.warn("生成举报人通知失败，举报ID：{}", lawyerUserViolation.getId());
                return;
            }

            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            int noticeResult = lifeNoticeMapper.insert(lifeNotice);
            if (noticeResult <= 0) {
                log.warn("保存举报人通知失败，举报ID：{}", lawyerUserViolation.getId());
                return;
            }

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

            log.info("举报人通知发送成功，接收人ID：{}", lifeNotice.getReceiverId());

        } catch (Exception e) {
            log.error("向举报人发送通知异常，举报ID：{}，异常信息：{}",
                    lawyerUserViolation.getId(), e.getMessage(), e);
        }
    }

    /**
     * 向被举报人发送通知
     *
     * @param lawyerUserViolation 举报信息对象
     */
    private void sendReportNoticeToReported(LawyerUserViolation lawyerUserViolation) {
        try {
            LifeNotice lifeNoticeReported = getLifeReportedNotice(lawyerUserViolation);
            if (lifeNoticeReported == null) {
                log.debug("无需向被举报人发送通知，举报ID：{}", lawyerUserViolation.getId());
                return;
            }

            lifeNoticeUtil.fillUserTypeAndRefId(lifeNoticeReported);
            int noticeResult = lifeNoticeMapper.insert(lifeNoticeReported);
            if (noticeResult <= 0) {
                log.warn("保存被举报人通知失败，举报ID：{}", lawyerUserViolation.getId());
                return;
            }

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

            log.info("被举报人通知发送成功，接收人ID：{}", lifeNoticeReported.getReceiverId());

        } catch (Exception e) {
            log.error("向被举报人发送通知异常，举报ID：{}，异常信息：{}",
                    lawyerUserViolation.getId(), e.getMessage(), e);
        }
    }

    /**
     * 构建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;
    }

    /**
     * 生成举报人通知消息
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 通知对象，如果生成失败返回null
     */
    private LifeNotice getLifeNotice(LawyerUserViolation lawyerUserViolation) {
        if (lawyerUserViolation == null) {
            log.warn("生成举报人通知失败，举报信息对象为空");
            return null;
        }

        try {
            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setSenderId(SYSTEM_SENDER_ID);
            lifeNotice.setBusinessId(lawyerUserViolation.getId());
            lifeNotice.setTitle("举报通知");

            // 获取举报人接收ID
            String receiverId = getReporterReceiverId(lawyerUserViolation);
            if (StringUtils.isEmpty(receiverId)) {
                log.warn("获取举报人接收ID失败，举报ID：{}", lawyerUserViolation.getId());
                return null;
            }
            lifeNotice.setReceiverId(receiverId);

            // 构建通知消息内容
            String message = buildReporterMessage(lawyerUserViolation);
            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：{}，异常信息：{}",
                    lawyerUserViolation.getId(), e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取举报人接收ID
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 接收人ID，格式：lawyer_/store_/user_ + 手机号
     */
    private String getReporterReceiverId(LawyerUserViolation lawyerUserViolation) {
        String reportingUserType = lawyerUserViolation.getReportingUserType();
        String reportingUserId = lawyerUserViolation.getReportingUserId();

        if (StringUtils.isEmpty(reportingUserId)) {
            log.warn("举报用户ID为空");
            return null;
        }

        String phone = null;
        if (USER_TYPE_LAWYER.equals(reportingUserType)) {
            LawyerUser lawyerUser = lawyerUserMapper.selectById(reportingUserId);
            if (lawyerUser != null && StringUtils.isNotEmpty(lawyerUser.getPhone())) {
                phone = lawyerUser.getPhone();
                return "lawyer_" + phone;
            }
        } else if (USER_TYPE_STORE.equals(reportingUserType)) {
            StoreUser storeUser = storeUserMapper.selectById(reportingUserId);
            if (storeUser != null && StringUtils.isNotEmpty(storeUser.getPhone())) {
                phone = storeUser.getPhone();
                return "store_" + phone;
            }
        } else if (USER_TYPE_LIFE.equals(reportingUserType)) {
            LifeUser lifeUser = lifeUserMapper.selectById(reportingUserId);
            if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserPhone())) {
                phone = lifeUser.getUserPhone();
                return "user_" + phone;
            }
        }

        log.warn("获取举报人手机号失败，用户类型：{}，用户ID：{}", reportingUserType, reportingUserId);
        return null;
    }

    /**
     * 构建举报人通知消息内容
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 消息内容
     */
    private String buildReporterMessage(LawyerUserViolation lawyerUserViolation) {
        String reportContextType = lawyerUserViolation.getReportContextType();

        // 如果举报内容类型不包含"6"，返回默认消息
        if (StringUtils.isEmpty(reportContextType) || !reportContextType.contains("6")) {
            return DEFAULT_NOTICE_MESSAGE;
        }

        try {
            // 获取被举报用户名称
            String reportedUserName = getReportedUserName(lawyerUserViolation);
            if (StringUtils.isEmpty(reportedUserName)) {
                log.warn("获取被举报用户名称失败，使用默认消息");
                return DEFAULT_NOTICE_MESSAGE;
            }

            // 格式化时间
            SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_FORMAT);
            String reportDate = dateFormat.format(new Date());

            // 获取违规原因
            String violationReason = getViolationReason(lawyerUserViolation);

            return String.format("您%s举报%s律师%s，已提交至平台审核，1-3个工作日会发送您审核结果，请注意查收。",
                    reportDate, reportedUserName, violationReason);

        } catch (Exception e) {
            log.error("构建举报人消息异常，使用默认消息，异常信息：{}", e.getMessage(), e);
            return DEFAULT_NOTICE_MESSAGE;
        }
    }

    /**
     * 获取违规原因
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 违规原因文本
     */
    private String getViolationReason(LawyerUserViolation lawyerUserViolation) {
        String violationReasonId = lawyerUserViolation.getViolationReason();
        String violationReason = DEFAULT_VIOLATION_REASON;
        if (StringUtils.isEmpty(violationReasonId)) {
            return violationReason;
        }

        if(violationReasonId.equals("1")){
            violationReason = "服务态度差";
        } else if(violationReasonId.equals("2")){
            violationReason = "专业能力差";
        } else if(violationReasonId.equals("3")){
            violationReason = "响应时间超过24小时";
        }
        return violationReason;
    }

    /**
     * 获取被举报用户名称
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 被举报用户名称
     */
    private String getReportedUserName(LawyerUserViolation lawyerUserViolation) {
        String reportedUserType = lawyerUserViolation.getReportedUserType();
        String reportedUserId = lawyerUserViolation.getReportedUserId();

        if (StringUtils.isEmpty(reportedUserId)) {
            return null;
        }

        if (USER_TYPE_LAWYER.equals(reportedUserType)) {
            LawyerUser lawyerUser = lawyerUserMapper.selectById(reportedUserId);
            return lawyerUser != null ? lawyerUser.getName() : null;
        } else if (USER_TYPE_STORE.equals(reportedUserType)) {
            StoreUser storeUser = storeUserMapper.selectById(reportedUserId);
            return storeUser != null ? storeUser.getNickName() : null;
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(reportedUserId);
            return lifeUser != null ? lifeUser.getUserName() : null;
        }
    }

    /**
     * 获取举报用户名称
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 举报用户名称
     */
    private String getReportingUserName(LawyerUserViolation lawyerUserViolation) {
        String reportingUserType = lawyerUserViolation.getReportingUserType();
        String reportingUserId = lawyerUserViolation.getReportingUserId();

        if (StringUtils.isEmpty(reportingUserId)) {
            return null;
        }

        if (USER_TYPE_LAWYER.equals(reportingUserType)) {
            LawyerUser lawyerUser = lawyerUserMapper.selectById(reportingUserId);
            return lawyerUser != null ? lawyerUser.getName() : null;
        } else if (USER_TYPE_STORE.equals(reportingUserType)) {
            StoreUser storeUser = storeUserMapper.selectById(reportingUserId);
            return storeUser != null ? storeUser.getNickName() : null;
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(reportingUserId);
            return lifeUser != null ? lifeUser.getUserName() : null;
        }
    }

    /**
     * 生成被举报人通知消息
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 通知对象，如果不需要发送或生成失败返回null
     */
    private LifeNotice getLifeReportedNotice(LawyerUserViolation lawyerUserViolation) {
        if (lawyerUserViolation == null) {
            log.warn("生成被举报人通知失败，举报信息对象为空");
            return null;
        }

        // 只有举报内容类型为"6"时才需要向被举报人发送通知
        String reportContextType = lawyerUserViolation.getReportContextType();
        if (!"6".equals(reportContextType)) {
            return null;
        }

        try {
            // 获取被举报人接收ID
            String receiverId = getReportedReceiverId(lawyerUserViolation);
            if (StringUtils.isEmpty(receiverId)) {
                log.warn("获取被举报人接收ID失败，举报ID：{}", lawyerUserViolation.getId());
                return null;
            }

            // 构建通知消息
            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setSenderId(SYSTEM_SENDER_ID);
            lifeNotice.setBusinessId(lawyerUserViolation.getId());
            lifeNotice.setTitle("咨询订单举报通知");
            lifeNotice.setReceiverId(receiverId);

            // 构建消息内容
            String message = buildReportedMessage(lawyerUserViolation);
            if (StringUtils.isEmpty(message)) {
                return null;
            }

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("message", message);
            lifeNotice.setContext(jsonObject.toJSONString());
            lifeNotice.setNoticeType(1);
            lifeNotice.setBusinessType(1);

            return lifeNotice;

        } catch (Exception e) {
            log.error("生成被举报人通知异常，举报ID：{}，异常信息：{}",
                    lawyerUserViolation.getId(), e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取被举报人接收ID
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 接收人ID，格式：lawyer_/store_/user_ + 手机号
     */
    private String getReportedReceiverId(LawyerUserViolation lawyerUserViolation) {
        String reportedUserType = lawyerUserViolation.getReportedUserType();
        String reportedUserId = lawyerUserViolation.getReportedUserId();

        if (StringUtils.isEmpty(reportedUserId)) {
            log.warn("被举报用户ID为空");
            return null;
        }

        String phone = null;
        if (USER_TYPE_LAWYER.equals(reportedUserType)) {
            LawyerUser lawyerUser = lawyerUserMapper.selectById(reportedUserId);
            if (lawyerUser != null && StringUtils.isNotEmpty(lawyerUser.getPhone())) {
                phone = lawyerUser.getPhone();
                return "lawyer_" + phone;
            }
        } else if (USER_TYPE_STORE.equals(reportedUserType)) {
            StoreUser storeUser = storeUserMapper.selectById(reportedUserId);
            if (storeUser != null && StringUtils.isNotEmpty(storeUser.getPhone())) {
                phone = storeUser.getPhone();
                return "store_" + phone;
            }
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(reportedUserId);
            if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserPhone())) {
                phone = lifeUser.getUserPhone();
                return "user_" + phone;
            }
        }

        log.warn("获取被举报人手机号失败，用户类型：{}，用户ID：{}", reportedUserType, reportedUserId);
        return null;
    }

    /**
     * 构建被举报人通知消息内容
     *
     * @param lawyerUserViolation 举报信息对象
     * @return 消息内容
     */
    private String buildReportedMessage(LawyerUserViolation lawyerUserViolation) {
        try {
            // 获取违规类型文本
            String violationType = lawyerUserViolation.getViolationReason();
            if (StringUtils.isEmpty(violationType)) {
                log.warn("违规类型为空，无法构建被举报人消息");
                return null;
            }

            String violationText = EnumUtil.getStatusValue(Integer.parseInt(violationType));

            // 格式化时间
            SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_FORMAT);
            String reportDate = dateFormat.format(new Date());

            return String.format("您在%s被举报涉嫌%s，平台将会进行核实。如确实存在违规行为，平台将禁用您的账号**天，到期后账号可恢复使用，应用内的环境需要我们共同维护。",
                    reportDate, violationText);

        } catch (Exception e) {
            log.error("构建被举报人消息异常，异常信息：{}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public Map<String, Object> reportListByUserId(String userId) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        LambdaUpdateWrapper<LawyerUserViolation> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LawyerUserViolation::getReportingUserId, userId).orderByDesc(LawyerUserViolation::getCreatedTime);
        List<LawyerUserViolation> lawyerUserViolations = lawyerUserViolationMapper.selectList(wrapper);
        List<LawyerUserViolation> filteredViolations = lawyerUserViolations.stream().filter(violation -> !"0".equals(violation.getProcessingStatus())).collect(Collectors.toList());
        List<LawyerUserViolationVo> lawyerUserViolationsVo = new ArrayList<>();
        for (LawyerUserViolation violation : filteredViolations) {
            LawyerUserViolationVo vo = new LawyerUserViolationVo();
            BeanUtils.copyProperties(violation, vo);
            lawyerUserViolationsVo.add(vo);
        }
        lawyerUserViolationsVo.forEach(lawyerUserViolationVo -> {
            lawyerUserViolationVo.setReportResultNotification("举报结果通知");
        });
        if (!lawyerUserViolations.isEmpty()) {
            resultMap.put("createTime", lawyerUserViolations.get(0).getCreatedTime());
            resultMap.put("data", lawyerUserViolationsVo);
        }
        return resultMap;
    }

    /**
     * 根据ID查询举报详情
     * <p>
     * 根据举报ID查询举报详细信息，包括被举报人信息、举报原因、举报凭证等
     * </p>
     *
     * @param id 举报记录ID，不能为空
     * @return 举报详情VO对象，如果记录不存在返回null
     * @throws RuntimeException 当参数无效或查询异常时抛出
     * @author system
     * @since 2025-01-XX
     */
    @Override
    public LawyerUserViolationVo reportListById(String id) {
        // 参数校验
        if (StringUtils.isEmpty(id)) {
            log.warn("查询举报详情参数为空，ID：{}", id);
            throw new RuntimeException("举报ID不能为空");
        }

        try {
            // 查询举报记录
            LawyerUserViolation lawyerUserViolation = lawyerUserViolationMapper.selectById(id);
            if (lawyerUserViolation == null) {
                log.warn("举报记录不存在，ID：{}", id);
                return null;
            }

            // 构建VO对象
            LawyerUserViolationVo violationVo = new LawyerUserViolationVo();
            BeanUtils.copyProperties(lawyerUserViolation, violationVo);

            // 获取被举报用户名称
            String reportedUserName = getReportedUserName(lawyerUserViolation);
            violationVo.setReportedUserName(reportedUserName);

            // 获取举报用户名称
            String reportingUserName = getReportingUserName(lawyerUserViolation);
            violationVo.setReportUserName(reportingUserName);

            log.info("查询举报详情成功，ID：{}", id);
            return violationVo;

        } catch (Exception e) {
            log.error("查询举报详情异常，ID：{}，异常信息：{}", id, e.getMessage(), e);
            throw new RuntimeException("查询举报详情失败：" + e.getMessage(), e);
        }
    }

    /**
     * 分页查询违规举报信息
     * <p>
     * 根据查询条件分页查询律师用户违规举报信息，支持按订单号、处理状态、
     * 被举报人名称、违规原因、手机号、时间范围等条件进行筛选查询
     * </p>
     *
     * @param pageNum          当前页码，从1开始，必须大于0
     * @param pageSize         每页大小，必须大于0且不超过最大值
     * @param orderNumber          订单号，支持模糊查询，可为空
     * @param phone            举报人手机号，精确匹配，可为空
     * @param processingStatus 处理状态，精确匹配，可为空
     * @param reportedUserName 被举报人名称，支持模糊查询，可为空
     * @param reportedPhone    被举报人手机号，精确匹配，可为空
     * @param violationReason  违规原因，精确匹配，可为空
     * @param startTime        开始时间，格式：yyyy-MM-dd HH:mm:ss，可为空
     * @param endTime          结束时间，格式：yyyy-MM-dd HH:mm:ss，可为空
     * @return 分页查询结果，包含违规举报DTO列表
     * @throws RuntimeException 当分页参数无效或查询异常时抛出
     * @author system
     * @since 2025-01-XX
     */
    @Override
    public IPage<LawyerUserViolationDto> getViolationPage(int pageNum, int pageSize, String orderNumber,
                                                           String phone, String processingStatus,
                                                           String reportedUserName, String reportedPhone,
                                                           String violationReason, String startTime,
                                                           String endTime) {
        // 参数校验
        validatePageParams(pageNum, pageSize);

        try {
            // 构建分页对象
            IPage<LawyerUserViolationVo> pageRequest = new Page<>(pageNum, pageSize);

            // 构建查询条件
            QueryWrapper<LawyerUserViolationVo> queryWrapper = buildQueryWrapper(orderNumber, phone,
                    processingStatus, reportedUserName, reportedPhone, violationReason, startTime, endTime);

            // 执行分页查询
            IPage<LawyerUserViolationVo> resultPage = lawyerUserViolationMapper.getViolationPage(pageRequest,
                    queryWrapper);

            // 转换为DTO并处理数据
            return convertToDtoPage(resultPage);

        } catch (RuntimeException e) {
            log.error("分页查询违规举报信息业务异常，页码：{}，每页大小：{}，异常信息：{}",
                    pageNum, pageSize, e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("分页查询违规举报信息异常，页码：{}，每页大小：{}，异常信息：{}",
                    pageNum, pageSize, e.getMessage(), e);
            throw new RuntimeException("分页查询违规举报信息失败：" + e.getMessage(), e);
        }
    }

    /**
     * 校验分页参数
     *
     * @param page 当前页码
     * @param size 每页大小
     * @throws RuntimeException 当参数无效时抛出
     */
    private void validatePageParams(int page, int size) {
        if (page < 1) {
            log.warn("分页查询参数无效，页码：{}", page);
            throw new RuntimeException("页码必须大于0");
        }
        if (size < 1) {
            log.warn("分页查询参数无效，每页大小：{}", size);
            throw new RuntimeException("每页大小必须大于0");
        }
        if (size > MAX_PAGE_SIZE) {
            log.warn("分页查询参数无效，每页大小超过最大值：{}", size);
            throw new RuntimeException("每页大小不能超过" + MAX_PAGE_SIZE);
        }
    }

    /**
     * 构建查询条件
     * <p>
     * 根据传入的查询参数动态构建查询条件，支持多条件组合查询
     * </p>
     *
     * @param orderId          订单号，支持模糊查询
     * @param phone            举报人手机号，精确匹配
     * @param processingStatus 处理状态，精确匹配
     * @param reportedUserName 被举报人名称，支持模糊查询
     * @param reportedPhone    被举报人手机号，精确匹配
     * @param violationReason  违规原因，精确匹配
     * @param startTime        开始时间，大于等于查询
     * @param endTime          结束时间，小于等于查询
     * @return 查询条件包装器
     */
    private QueryWrapper<LawyerUserViolationVo> buildQueryWrapper(String orderId, String phone,
                                                                    String processingStatus,
                                                                    String reportedUserName,
                                                                    String reportedPhone,
                                                                    String violationReason,
                                                                    String startTime, String endTime) {
        QueryWrapper<LawyerUserViolationVo> queryWrapper = new QueryWrapper<>();

        // 基础查询条件：未删除且为订单举报
        queryWrapper.eq("luv.delete_flag", DELETE_FLAG_NOT_DELETED)
                .eq("luv.report_context_type", REPORT_CONTEXT_TYPE_ORDER);

        // 动态查询条件：订单号模糊查询
        if (StringUtils.isNotEmpty(orderId)) {
            queryWrapper.like("luv.order_number", orderId);
        }

        // 动态查询条件：举报人手机号精确匹配
        if (StringUtils.isNotEmpty(phone)) {
            queryWrapper.eq("ui.phone", phone);
        }

        // 动态查询条件：处理状态精确匹配
        if (StringUtils.isNotEmpty(processingStatus)) {
            queryWrapper.eq("luv.processing_status", processingStatus);
        }

        // 动态查询条件：被举报人名称模糊查询
        if (StringUtils.isNotEmpty(reportedUserName)) {
            queryWrapper.like("ui_reported.nick_name", reportedUserName);
        }

        // 动态查询条件：被举报人手机号精确匹配
        if (StringUtils.isNotEmpty(reportedPhone)) {
            queryWrapper.eq("ui_reported.phone", reportedPhone);
        }

        // 动态查询条件：违规原因精确匹配
        if (StringUtils.isNotEmpty(violationReason)) {
            queryWrapper.eq("luv.violation_reason", violationReason);
        }

        // 动态查询条件：开始时间范围查询（大于等于）
        if (StringUtils.isNotEmpty(startTime)) {
            queryWrapper.ge("luv.created_time", startTime);
        }

        // 动态查询条件：结束时间范围查询（小于等于）
        if (StringUtils.isNotEmpty(endTime)) {
            queryWrapper.le("luv.created_time", endTime);
        }

        // 排序：按更新时间倒序
        queryWrapper.orderByDesc("luv.updated_time");

        return queryWrapper;
    }

    /**
     * 将VO分页结果转换为DTO分页结果
     *
     * @param voPage VO分页结果
     * @return DTO分页结果
     */
    private IPage<LawyerUserViolationDto> convertToDtoPage(IPage<LawyerUserViolationVo> voPage) {
        return voPage.convert(this::convertToDto);
    }

    /**
     * 将VO对象转换为DTO对象
     *
     * @param vo VO对象
     * @return DTO对象
     */
    private LawyerUserViolationDto convertToDto(LawyerUserViolationVo vo) {
        LawyerUserViolationDto dto = new LawyerUserViolationDto();
        BeanUtils.copyProperties(vo, dto);

        // 处理举报凭证图片
        processReportEvidenceImages(vo, dto);

        // 设置用户名称信息
        setUserNames(vo, dto);

        return dto;
    }

    /**
     * 处理举报凭证图片
     *
     * @param vo  VO对象
     * @param dto DTO对象
     */
    private void processReportEvidenceImages(LawyerUserViolationVo vo, LawyerUserViolationDto dto) {
        if (Objects.isNull(vo.getReportEvidenceImg())) {
            dto.setImage("");
            dto.setImageList(new ArrayList<>());
            return;
        }

        List<String> imageList = Arrays.stream(vo.getReportEvidenceImg().split(IMAGE_SEPARATOR))
                .map(String::trim)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toList());

        if (!imageList.isEmpty()) {
            dto.setImage(imageList.get(0));
            dto.setImageList(imageList);
        } else {
            dto.setImage("");
            dto.setImageList(new ArrayList<>());
        }
    }

    /**
     * 设置用户名称信息
     *
     * @param vo  VO对象
     * @param dto DTO对象
     */
    private void setUserNames(LawyerUserViolationVo vo, LawyerUserViolationDto dto) {
        dto.setNickname(vo.getNickName());
        dto.setReportUserName(vo.getReportUserName());
        dto.setReportedUserName(vo.getReportedUserName());
    }

    /**
     * 审批举报
     * <p>
     * 处理举报审批，包括：
     * 1. 更新举报处理状态
     * 2. 更新订单状态为已退款
     * 3. 调用支付宝退款接口进行退款（如果退款失败，会回滚订单状态更新）
     * 4. 向举报人发送审批结果通知
     * 5. 向被举报人发送通知（如需要）
     * </p>
     *
     * @param id               举报记录ID
     * @param processingStatus 处理状态（1-通过，其他-驳回）
     * @param reportResult     处理结果说明
     * @author system
     * @since 2025-01-XX
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(int id, String processingStatus, String reportResult) {
        // 参数校验
        if (id <= 0 || StringUtils.isBlank(processingStatus)) {
            log.warn("审批举报参数无效，ID：{}，处理状态：{}", id, processingStatus);
            return;
        }

        try {
            // 查询举报记录
            LawyerUserViolation violation = lawyerUserViolationMapper.selectById(id);
            if (violation == null) {
                log.warn("举报记录不存在，ID：{}", id);
                return;
            }

            // 更新举报记录状态
            updateViolationStatus(violation, processingStatus, reportResult);

            // 根据举报处理进行订单状态翻转
            if (PROCESSING_STATUS_APPROVED.equals(processingStatus)) {
                // 审批通过
                LambdaUpdateWrapper<LawyerConsultationOrder> lawyerConsultationOrderLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                lawyerConsultationOrderLambdaUpdateWrapper.eq(LawyerConsultationOrder::getOrderNumber, violation.getOrderNumber());
                lawyerConsultationOrderLambdaUpdateWrapper.set(LawyerConsultationOrder::getOrderStatus, LawyerStatusEnum.REFUNDED.getStatus());
               int result = consultationOrderMapper.update(null, lawyerConsultationOrderLambdaUpdateWrapper);
               if (result > 0) {
                   log.info("订单状态更新成功，订单编号：{}", violation.getOrderNumber());

                   // 订单状态更新成功后进行退款
                   processRefund(violation.getOrderNumber());

                   // 构建并发送通知消息
                   sendApprovalNotifications(violation, processingStatus, reportResult);
               } else {
                   log.warn("订单状态更新失败，订单编号：{}", violation.getOrderNumber());
               }
            } else {
                // 审批驳回
                log.info("订单状态更新成功，订单编号：{}", violation.getOrderNumber());

                // 构建并发送通知消息
                sendApprovalNotifications(violation, processingStatus, reportResult);
            }


            log.info("审批举报处理完成，举报ID：{}，处理状态：{}", id, processingStatus);

        } catch (Exception e) {
            log.error("审批举报处理异常，举报ID：{}，异常信息：{}", id, e.getMessage(), e);
            throw new RuntimeException("审批举报处理失败：" + e.getMessage(), e);
        }
    }

    /**
     * 更新举报记录状态
     *
     * @param violation        举报记录
     * @param processingStatus 处理状态
     * @param reportResult     处理结果
     */
    private void updateViolationStatus(LawyerUserViolation violation, String processingStatus,
                                       String reportResult) {
        violation.setProcessingStatus(processingStatus);
        violation.setProcessingTime(new Date());
        violation.setReportResult(reportResult);
        lawyerUserViolationMapper.updateById(violation);
    }

    /**
     * 处理订单退款
     * <p>
     * 根据订单号查询订单信息，调用支付宝退款接口进行退款
     * 如果退款失败，会抛出异常以触发事务回滚
     * </p>
     *
     * @param orderNumber 订单号
     * @throws RuntimeException 当退款失败时抛出异常，触发事务回滚
     */
    private void processRefund(String orderNumber) {
        if (StringUtils.isEmpty(orderNumber)) {
            log.error("处理退款失败：订单号为空");
            throw new RuntimeException("订单号不能为空，无法处理退款");
        }

        try {
            // 查询订单信息
            LambdaQueryWrapper<LawyerConsultationOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(LawyerConsultationOrder::getOrderNumber, orderNumber)
                    .eq(LawyerConsultationOrder::getDeleteFlag, 0)
                    .last("LIMIT 1");
            LawyerConsultationOrder order = consultationOrderMapper.selectOne(queryWrapper);

            if (order == null) {
                log.error("处理退款失败：订单不存在，订单号：{}", orderNumber);
                throw new RuntimeException("订单不存在，无法处理退款，订单号：" + orderNumber);
            }

            // 检查订单是否有支付宝交易号
            if (StringUtils.isEmpty(order.getAlipayNo())) {
                log.error("处理退款失败：订单无支付宝交易号，订单号：{}", orderNumber);
                throw new RuntimeException("订单无支付宝交易号，无法处理退款，订单号：" + orderNumber);
            }

            // 检查订单金额
            if (order.getOrderAmount() == null || order.getOrderAmount() <= 0) {
                log.error("处理退款失败：订单金额无效，订单号：{}，订单金额：{}", orderNumber, order.getOrderAmount());
                throw new RuntimeException("订单金额无效，无法处理退款，订单号：" + orderNumber);
            }

            // 将订单金额从分转换为元
            BigDecimal refundAmount = new BigDecimal(order.getOrderAmount())
                    .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);

            // 退款原因
            String refundReason = "举报审核通过，订单退款";

            // 调用支付宝退款接口
            log.info("开始处理订单退款，订单号：{}，支付宝交易号：{}，退款金额：{}元", 
                    orderNumber, order.getAlipayNo(), refundAmount.toString());
            
            String refundResult = aliApi.processRefund(order.getAlipayNo(), refundAmount.toString(), refundReason, "");
            
            if ("调用成功".equals(refundResult)) {
                log.info("订单退款成功，订单号：{}，退款金额：{}元", orderNumber, refundAmount.toString());
            } else {
                log.error("订单退款失败，订单号：{}，退款结果：{}", orderNumber, refundResult);
                // 退款失败时抛出异常，触发事务回滚
                throw new RuntimeException("订单退款失败，订单号：" + orderNumber + "，退款结果：" + refundResult);
            }

        } catch (RuntimeException e) {
            // 重新抛出RuntimeException，触发事务回滚
            log.error("处理订单退款失败，订单号：{}，异常信息：{}", orderNumber, e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            // 其他异常也转换为RuntimeException，触发事务回滚
            log.error("处理订单退款异常，订单号：{}，异常信息：{}", orderNumber, e.getMessage(), e);
            throw new RuntimeException("处理订单退款时发生异常，订单号：" + orderNumber + "，异常信息：" + e.getMessage(), e);
        }
    }

    /**
     * 发送审批通知消息
     *
     * @param violation        举报记录
     * @param processingStatus 处理状态
     * @param reportResult     处理结果
     */
    private void sendApprovalNotifications(LawyerUserViolation violation, String processingStatus,
                                           String reportResult) {
        // 构建举报人通知消息
        NotificationInfo reporterNotification = buildReporterNotification(violation, processingStatus,
                reportResult);
        if (reporterNotification != null && StringUtils.isNotEmpty(reporterNotification.getMessage())) {
            sendNotificationToReporter(violation, reporterNotification);
        }

        // 构建被举报人通知消息（仅通过且为订单举报时）
        if (PROCESSING_STATUS_APPROVED.equals(processingStatus)
                && REPORT_CONTEXT_TYPE_ORDER.equals(violation.getReportContextType())) {
            NotificationInfo reportedNotification = buildReportedNotification(violation);
            if (reportedNotification != null && StringUtils.isNotEmpty(reportedNotification.getMessage())) {
                sendNotificationToReported(violation, reportedNotification);
            }
        }
    }

    /**
     * 构建举报人通知信息
     *
     * @param violation        举报记录
     * @param processingStatus 处理状态
     * @param reportResult     处理结果
     * @return 通知信息
     */
    private NotificationInfo buildReporterNotification(LawyerUserViolation violation,
                                                        String processingStatus, String reportResult) {
        NotificationInfo notificationInfo = new NotificationInfo();
        String reportContextType = violation.getReportContextType();

        if (PROCESSING_STATUS_APPROVED.equals(processingStatus)) {
            // 审批通过
            if (REPORT_CONTEXT_TYPE_ORDER.equals(reportContextType)) {
                notificationInfo.setMessage("您举报律师服务态度差，经核实，确实存在此行为，"
                        + "订单金额将在1-3个工作日原路返还，请注意查收。");
                notificationInfo.setTitle("举报成功通知");
            }
        } else {
            // 审批驳回
            if (REPORT_CONTEXT_TYPE_ORDER.equals(reportContextType)) {
                String message = "您举报律师服务态度差，经核实，不存在此行为，订单金额不予退还。";
                if (StringUtils.isNotEmpty(reportResult)) {
                    message += "拒绝原因：" + reportResult;
                }
                notificationInfo.setMessage(message);
                notificationInfo.setTitle("举报失败通知");
            }
        }

        return notificationInfo;
    }

    /**
     * 构建被举报人通知信息
     *
     * @param violation 举报记录
     * @return 通知信息
     */
    private NotificationInfo buildReportedNotification(LawyerUserViolation violation) {
        NotificationInfo notificationInfo = new NotificationInfo();
        String orderId = violation.getOrderNumber();
        String message = String.format("用户对编号为%s的订单进行申诉，经核实，用户举报属实，"
                + "订单金额将会退还给用户。", orderId);
        notificationInfo.setMessage(message);
        notificationInfo.setTitle("被举报成功通知");
        return notificationInfo;
    }

    /**
     * 向举报人发送通知
     *
     * @param violation         举报记录
     * @param notificationInfo 通知信息
     */
    private void sendNotificationToReporter(LawyerUserViolation violation,
                                             NotificationInfo notificationInfo) {
        try {
            // 获取举报人接收ID
            String receiverId = getReporterReceiverId(violation);
            if (StringUtils.isEmpty(receiverId)) {
                log.warn("获取举报人接收ID失败，举报ID：{}", violation.getId());
                return;
            }

            // 创建并保存通知
            LifeNotice lifeNotice = createLifeNotice(violation.getId(), receiverId,
                    notificationInfo.getTitle(), notificationInfo.getMessage());
            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            lifeNoticeMapper.insert(lifeNotice);

            // 发送WebSocket消息
            sendWebSocketMessage(receiverId, lifeNotice);



            // 创建并保存到账通知

            String notificationInfo1 = "您的编号为" + violation.getOrderNumber() + "的订单，订单金额已原路返还至您的支付渠道，请查收";
            LifeNotice lifeNotice1 = createLifeNotice(violation.getId(), receiverId,
                    "退款到账通知", notificationInfo1);
            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice1);
            lifeNoticeMapper.insert(lifeNotice1);

            // 发送WebSocket消息
            sendWebSocketMessage(receiverId, lifeNotice1);



            log.info("举报人通知发送成功，接收人ID：{}", receiverId);

        } catch (Exception e) {
            log.error("向举报人发送通知异常，举报ID：{}，异常信息：{}", violation.getId(), e.getMessage(), e);
        }
    }

    /**
     * 向被举报人发送通知
     *
     * @param violation         举报记录
     * @param notificationInfo 通知信息
     */
    private void sendNotificationToReported(LawyerUserViolation violation,
                                            NotificationInfo notificationInfo) {
        try {
            // 获取被举报人接收ID
            String receiverId = getReportedReceiverId(violation);
            if (StringUtils.isEmpty(receiverId)) {
                log.warn("获取被举报人接收ID失败，举报ID：{}", violation.getId());
                return;
            }

            // 创建并保存通知
            LifeNotice lifeNotice = createLifeNotice(violation.getId(), receiverId,
                    notificationInfo.getTitle(), notificationInfo.getMessage());
            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            lifeNoticeMapper.insert(lifeNotice);

            // 发送WebSocket消息
            sendWebSocketMessage(receiverId, lifeNotice);

            log.info("被举报人通知发送成功，接收人ID：{}", receiverId);

        } catch (Exception e) {
            log.error("向被举报人发送通知异常，举报ID：{}，异常信息：{}", violation.getId(), e.getMessage(), e);
        }
    }

    /**
     * 创建通知对象
     *
     * @param businessId 业务ID（举报ID）
     * @param receiverId 接收人ID
     * @param title      通知标题
     * @param message    通知消息
     * @return 通知对象
     */
    private LifeNotice createLifeNotice(Integer businessId, String receiverId, String title,
                                        String message) {
        LifeNotice lifeNotice = new LifeNotice();
        lifeNotice.setSenderId(SYSTEM_SENDER_ID);
        lifeNotice.setBusinessId(businessId);
        lifeNotice.setReceiverId(receiverId);
        lifeNotice.setTitle(title);
        lifeNotice.setNoticeType(1);
        lifeNotice.setIsRead(0);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", message);
        lifeNotice.setContext(jsonObject.toJSONString());
        lifeNotice.setBusinessType(1);

        return lifeNotice;
    }

    /**
     * 发送WebSocket消息
     *
     * @param receiverId 接收人ID
     * @param lifeNotice 通知对象
     */
    private void sendWebSocketMessage(String receiverId, LifeNotice lifeNotice) {
        try {
            WebSocketVo webSocketVo = buildWebSocketVo(lifeNotice);
            webSocketProcess.sendMessage(receiverId, JSONObject.from(webSocketVo).toJSONString());
        } catch (Exception e) {
            log.error("发送WebSocket消息异常，接收人ID：{}，异常信息：{}", receiverId, e.getMessage(), e);
        }
    }

    /**
     * 通知信息内部类
     */
    private static class NotificationInfo {
        private String title;
        private String message;

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }


    @Override
    public LawyerUserViolationDto byId(Integer id) {
        LawyerUserViolation entity = lawyerUserViolationMapper.selectById(id);
        if (entity == null) return null;
        LawyerUserViolationDto dto = new LawyerUserViolationDto();
        BeanUtils.copyProperties(entity, dto);
        if (Objects.nonNull(entity.getReportEvidenceImg())) {
            List<String> list = Arrays.stream(entity.getReportEvidenceImg().split(",")).map(String::trim).collect(Collectors.toList());
            dto.setImageList(list);
        }
        // 处理举报人信息
        if ("3".equals(dto.getReportingUserType())) {
            LawyerUser lawyerUser = lawyerUserService.getById(dto.getReportingUserId());
            if (lawyerUser != null) {
                dto.setNickname(lawyerUser.getName());
                dto.setPhone(lawyerUser.getPhone());
            }
        } else if ("1".equals(dto.getReportingUserType())) {
            StoreUser storeUser = storeUserMapper.selectById(dto.getReportingUserId());
            if (storeUser != null) {
                dto.setNickname(storeUser.getNickName());
                dto.setPhone(storeUser.getPhone());
            }
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(dto.getReportingUserId());
            if (lifeUser != null) {
                dto.setNickname(lifeUser.getUserName());
                dto.setPhone(lifeUser.getUserPhone());
            }
        }
        // 处理被举报人信息
        if ("lawyer".equals(dto.getReportedUserType())) {
            LawyerUser lawyerUser = lawyerUserService.getById(dto.getReportedUserId());
            if (lawyerUser != null) {
                dto.setAccount(lawyerUser.getPhone());
            }
        } else if ("1".equals(dto.getReportedUserType())) {
            StoreUser storeUser = storeUserMapper.selectById(dto.getReportedUserId());
            if (storeUser != null) {
                dto.setAccount(storeUser.getPhone());
            }
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(dto.getReportedUserId());
            if (lifeUser != null) {
                dto.setAccount(lifeUser.getUserPhone());
            }
        }
        return dto;
    }

    @Override
    public LawyerUserViolationDto byIdNotice(Integer id) {
        LifeNotice lifeNotice = lifeNoticeMapper.selectById(id);
        LawyerUserViolationDto dto = byId(lifeNotice.getBusinessId());
        dto.setLifeNotice(lifeNotice.getContext());
        return dto;
    }

    @Override
    public String exportExcel(String nickName, String phone, String processingStatus) throws IOException {
        // Excel导出功能，可以根据需要实现
        return "";
    }

    @Override
    public String level(UserLoginInfo userLoginInfo) {
        if (null == userLoginInfo) {
            return "O";
        }
        String type = userLoginInfo.getType();
        LambdaQueryWrapper<LawyerUserViolation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LawyerUserViolation::getReportContextType, "1").eq(LawyerUserViolation::getReportedUserId, userLoginInfo.getUserId());
        if (Objects.equals(type, "lawyer")) {
            wrapper.eq(LawyerUserViolation::getReportedUserType, "lawyer");
        } else if (Objects.equals(type, "store")) {
            wrapper.eq(LawyerUserViolation::getReportedUserType, "1");
        } else if (Objects.equals(type, "user")) {
            wrapper.eq(LawyerUserViolation::getReportedUserType, "2");
        }
        int count = Optional.ofNullable(lawyerUserViolationMapper.selectList(wrapper)).map(List::size).orElse(0);
        if (count == 0) return "O";
        if (count >= 15) return "E";
        if (count >= 10) return "D";
        if (count >= 6) return "C";
        if (count >= 3) return "B";
        return "A";
    }

    /**
     * 获取举报原因列表
     * <p>
     * 查询所有未删除的律师违规举报原因字典数据，按类型名称过滤
     * </p>
     *
     * @return 举报原因字典列表，如果查询失败或没有数据则返回空列表
     * @author system
     * @since 2025-01-XX
     */
    @Override
    public List<StoreDictionary> getViolationReason() {
        log.info("开始查询举报原因列表");
        try {
            LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StoreDictionary::getDeleteFlag, 0)
                    .eq(StoreDictionary::getTypeName, "lawyerViolationReason")
                    .orderByAsc(StoreDictionary::getId);

            List<StoreDictionary> violationReasonList = storeDictionaryMapper.selectList(queryWrapper);
            log.info("查询举报原因列表成功，共{}条记录", violationReasonList.size());
            return violationReasonList != null ? violationReasonList : new ArrayList<>();
        } catch (Exception e) {
            log.error("查询举报原因列表异常，异常信息：{}", e.getMessage(), e);
            throw new RuntimeException("查询举报原因列表失败：" + e.getMessage(), e);
        }
    }

    /**
     * 根据订单ID查询举报详情
     * <p>
     * 查询举报详情信息，包括举报的详情信息、订单的详情信息以及订单律师名字相关信息
     * </p>
     * <p>
     * 处理流程：
     * 1. 参数校验：订单ID必须大于0
     * 2. 查询举报详情：通过Mapper查询订单、举报、律师关联信息
     * 3. 校验举报信息：检查是否存在举报记录（violationId不为null）
     * 4. 填充举报人姓名：根据举报人ID查询并设置举报人姓名
     * 5. 设置订单价格字符串：根据收费方式格式化价格显示
     * </p>
     *
     * @param orderId 订单ID，必须大于0
     * @return 举报详情VO对象，包含举报信息、订单信息、律师信息，如果订单不存在或未举报则返回null
     * @throws IllegalArgumentException 当订单ID无效时抛出
     * @throws RuntimeException        当查询异常时抛出
     * @author system
     * @since 2025-01-XX
     */
    @Override
    public LawyerViolationDetailVO getViolationDetailByOrderId(Integer orderId) {
        log.info("根据订单ID查询举报详情开始，orderId={}", orderId);

        // 参数校验
        validateOrderIdForViolationDetail(orderId);

        try {
            // 查询举报详情
            LawyerViolationDetailVO detailVO = queryViolationDetailByOrderId(orderId);
            if (detailVO == null) {
                log.warn("根据订单ID查询举报详情：订单不存在，orderId={}", orderId);
                return null;
            }

            // 检查是否存在举报信息（如果violationId为null，说明没有举报记录）
            if (!hasViolationInfo(detailVO)) {
                log.warn("根据订单ID查询举报详情：订单存在但没有举报信息，orderId={}", orderId);
                return null;
            }

            // 填充举报详情附加信息
            fillViolationDetailAdditionalInfo(detailVO);

            log.info("根据订单ID查询举报详情成功，orderId={}, violationId={}, orderNumber={}",
                    orderId, detailVO.getViolationId(), detailVO.getOrderNumber());
            return detailVO;

        } catch (IllegalArgumentException e) {
            log.warn("根据订单ID查询举报详情参数校验失败，orderId={}，错误信息：{}", orderId, e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("根据订单ID查询举报详情异常，orderId={}，异常信息：{}", orderId, e.getMessage(), e);
            throw new RuntimeException("查询举报详情失败：" + e.getMessage(), e);
        }
    }

    /**
     * 校验订单ID（用于查询举报详情）
     * <p>
     * 检查订单ID是否为空或无效
     * </p>
     *
     * @param orderId 订单ID
     * @throws IllegalArgumentException 当订单ID为空或无效时抛出
     */
    private void validateOrderIdForViolationDetail(Integer orderId) {
        if (orderId == null) {
            log.warn("根据订单ID查询举报详情参数校验失败：订单ID为null");
            throw new IllegalArgumentException("订单ID不能为空");
        }

        if (orderId <= 0) {
            log.warn("根据订单ID查询举报详情参数校验失败：订单ID无效，orderId={}", orderId);
            throw new IllegalArgumentException("订单ID必须大于0");
        }
    }

    /**
     * 查询举报详情
     * <p>
     * 通过Mapper查询订单、举报、律师关联信息
     * </p>
     *
     * @param orderId 订单ID
     * @return 举报详情VO对象，如果订单不存在返回null
     */
    private LawyerViolationDetailVO queryViolationDetailByOrderId(Integer orderId) {
        try {
            LawyerViolationDetailVO detailVO = consultationOrderMapper.getViolationDetailByOrderId(orderId);
            if (detailVO != null) {
                log.debug("查询举报详情成功，orderId={}, orderNumber={}", orderId, detailVO.getOrderNumber());
            }
            return detailVO;
        } catch (Exception e) {
            log.error("查询举报详情数据库异常，orderId={}，异常信息：{}", orderId, e.getMessage(), e);
            throw new RuntimeException("查询举报详情失败：" + e.getMessage(), e);
        }
    }

    /**
     * 检查是否存在举报信息
     * <p>
     * 通过检查violationId是否为null来判断是否存在举报记录
     * </p>
     *
     * @param detailVO 举报详情VO对象
     * @return true表示存在举报信息，false表示不存在
     */
    private boolean hasViolationInfo(LawyerViolationDetailVO detailVO) {
        return detailVO != null && detailVO.getViolationId() != null;
    }

    /**
     * 填充举报详情附加信息
     * <p>
     * 填充举报人姓名和订单价格字符串等附加信息
     * </p>
     *
     * @param detailVO 举报详情VO对象
     */
    private void fillViolationDetailAdditionalInfo(LawyerViolationDetailVO detailVO) {
        if (detailVO == null) {
            return;
        }

        // 填充举报人姓名
        fillReportingUserName(detailVO);

        // 设置订单价格字符串
        setOrderPriceStr(detailVO);
    }

    /**
     * 填充举报人姓名
     * <p>
     * 根据举报人类型和ID查询并设置举报人姓名
     * </p>
     *
     * @param detailVO 举报详情VO对象
     */
    private void fillReportingUserName(LawyerViolationDetailVO detailVO) {
        if (detailVO == null) {
            return;
        }

        String reportingUserId = detailVO.getReportingUserId();
        String reportingUserType = detailVO.getReportingUserType();

        if (StringUtils.isEmpty(reportingUserId)) {
            log.debug("举报人ID为空，无需填充举报人姓名");
            return;
        }

        if (StringUtils.isEmpty(reportingUserType)) {
            log.warn("举报人类型为空，无法确定查询表，reportingUserId={}", reportingUserId);
            return;
        }

        String reportingUserName = getReportingUserNameByTypeAndId(reportingUserType, reportingUserId);
        detailVO.setReportingUserName(reportingUserName);
        log.debug("填充举报人姓名成功，reportingUserType={}, reportingUserId={}, reportingUserName={}",
                reportingUserType, reportingUserId, reportingUserName);
    }

    /**
     * 金额单位转换：分转元
     */
    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;

    /**
     * 设置订单价格字符串
     * <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 detailVO 举报详情VO对象，不能为null
     */
    private void setOrderPriceStr(LawyerViolationDetailVO detailVO) {
        if (detailVO == null) {
            log.warn("设置订单价格字符串失败：举报详情VO对象为null");
            return;
        }

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

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

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

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

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

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

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

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

    /**
     * 根据用户类型和ID获取举报人姓名
     * <p>
     * 根据用户类型直接查询对应的表，提高查询效率：
     * 1. 律师用户（type='3'）：从lawyer_user表查询name字段
     * 2. 商户用户（type='1'）：从store_user表查询nick_name字段
     * 3. 普通用户（type='2'）：从life_user表查询user_name字段
     * </p>
     *
     * @param userType 用户类型，1：商户，2：用户，3：律师
     * @param userId   用户ID，不能为空
     * @return 用户姓名，如果用户不存在或查询异常则返回null
     */
    private String getReportingUserNameByTypeAndId(String userType, String userId) {
        if (StringUtils.isEmpty(userType)) {
            log.warn("获取举报人姓名失败：用户类型为空，userId={}", userId);
            return null;
        }

        if (StringUtils.isEmpty(userId)) {
            log.warn("获取举报人姓名失败：用户ID为空，userType={}", userType);
            return null;
        }

        try {
            // 根据用户类型直接查询对应的表，避免依次查询多张表
            if (USER_TYPE_LAWYER.equals(userType)) {
                // 律师用户：从lawyer_user表查询
                return queryLawyerUserName(userId);
            } else if (USER_TYPE_STORE.equals(userType)) {
                // 商户用户：从store_user表查询
                return queryStoreUserName(userId);
            } else if (USER_TYPE_LIFE.equals(userType)) {
                // 普通用户：从life_user表查询
                return queryLifeUserName(userId);
            } else {
                log.warn("获取举报人姓名失败：未知的用户类型，userType={}, userId={}", userType, userId);
                return null;
            }

        } catch (Exception e) {
            log.error("获取举报人姓名异常，userType={}, userId={}，异常信息：{}", userType, userId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 查询律师用户姓名
     * <p>
     * 从lawyer_user表查询律师用户姓名
     * </p>
     *
     * @param userId 用户ID
     * @return 律师用户姓名，如果用户不存在则返回null
     */
    private String queryLawyerUserName(String userId) {
        try {
            LawyerUser lawyerUser = lawyerUserMapper.selectById(userId);
            if (lawyerUser != null && StringUtils.isNotEmpty(lawyerUser.getName())) {
                log.debug("查询律师用户姓名成功，userId={}, userName={}", userId, lawyerUser.getName());
                return lawyerUser.getName();
            }
            log.debug("查询律师用户姓名：用户不存在或姓名为空，userId={}", userId);
            return null;
        } catch (Exception e) {
            log.error("查询律师用户姓名异常，userId={}，异常信息：{}", userId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 查询商户用户姓名
     * <p>
     * 从store_user表查询商户用户昵称
     * </p>
     *
     * @param userId 用户ID
     * @return 商户用户昵称，如果用户不存在则返回null
     */
    private String queryStoreUserName(String userId) {
        try {
            StoreUser storeUser = storeUserMapper.selectById(userId);
            if (storeUser != null && StringUtils.isNotEmpty(storeUser.getNickName())) {
                log.debug("查询商户用户姓名成功，userId={}, userName={}", userId, storeUser.getNickName());
                return storeUser.getNickName();
            }
            log.debug("查询商户用户姓名：用户不存在或姓名为空，userId={}", userId);
            return null;
        } catch (Exception e) {
            log.error("查询商户用户姓名异常，userId={}，异常信息：{}", userId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 查询普通用户姓名
     * <p>
     * 从life_user表查询普通用户姓名
     * </p>
     *
     * @param userId 用户ID
     * @return 普通用户姓名，如果用户不存在则返回null
     */
    private String queryLifeUserName(String userId) {
        try {
            LifeUser lifeUser = lifeUserMapper.selectById(userId);
            if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserName())) {
                log.debug("查询普通用户姓名成功，userId={}, userName={}", userId, lifeUser.getUserName());
                return lifeUser.getUserName();
            }
            log.debug("查询普通用户姓名：用户不存在或姓名为空，userId={}", userId);
            return null;
        } catch (Exception e) {
            log.error("查询普通用户姓名异常，userId={}，异常信息：{}", userId, e.getMessage(), e);
            return null;
        }
    }
}

