package shop.alien.second.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONArray;
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 io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.config.properties.RiskControlProperties;
import shop.alien.config.redis.BaseRedisService;
import shop.alien.entity.result.BusinessException;
import shop.alien.entity.second.*;
import shop.alien.entity.second.enums.SecondUserCreditScoreEnum;
import shop.alien.entity.second.vo.SecondEntrustUserDTO;
import shop.alien.entity.store.*;
import shop.alien.mapper.second.SecondRiskControlRecordMapper;
import shop.alien.entity.second.vo.SecondTradeRecordVo;
import shop.alien.entity.second.vo.SellerEvaluationVo;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.mapper.LifeMessageMapper;
import shop.alien.mapper.LifeNoticeMapper;
import shop.alien.util.type.LifeMessageUtil;
import shop.alien.util.type.LifeNoticeUtil;
import shop.alien.mapper.LifeUserMapper;
import shop.alien.mapper.StoreDictionaryMapper;
import shop.alien.mapper.second.*;
import shop.alien.second.feign.AlienStoreFeign;
import shop.alien.second.service.SecondTradeRecordService;
import shop.alien.util.common.JwtUtil;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 二手交易记录表 服务实现类
 * </p>
 *
 * @author qrs
 * @since 2025-07-07
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordMapper, SecondTradeRecord> implements SecondTradeRecordService {

    private final SecondTradeRecordMapper secondTradeRecordMapper;
    private final SecondTradeOperationMapper secondTradeOperationMapper;
    private final SecondGoodsMapper secondGoodsMapper;
    private final SecondGoodsRecordMapper secondGoodsRecordMapper;
    private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;
    private final SecondUserCreditMapper secondUserCreditMapper;
    private final SecondUserCreditRecordMapper secondUserCreditRecordMapper;
    private final LifeMessageMapper lifeMessageMapper;
    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeMessageUtil lifeMessageUtil;
    private final LifeNoticeUtil lifeNoticeUtil;
    private final LifeUserMapper lifeUserMapper;
    private final AlienStoreFeign alienStoreFeign;
    private final StoreDictionaryMapper storeDictionaryMapper;
    private final BaseRedisService baseRedisService;
    @Autowired
    private RiskControlProperties riskControlProperties;

    // 委托人信息
    private final SecondEntrustUserMapper secondEntrustUserMapper;

    private final Object lock = new Object();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createTrade(SecondEntrustUserDTO trade) throws Exception {
        try {
            synchronized (lock) {
                LocalDate now = LocalDate.now();
                LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
                wrapper.between(SecondTradeRecord::getCreatedTime, now + " 00:00:00", now + " 23:59:59");
                int count = secondTradeRecordMapper.selectCount(wrapper);
                String tradeNo = "S" + now.toString().replace("-", "") + String.format("%05d", count + 1);
                trade.setTradeNo(tradeNo);
            }
            LambdaQueryWrapper<SecondGoodsRecord> goodsWrapper = new LambdaQueryWrapper<>();
            goodsWrapper.eq(SecondGoodsRecord::getGoodsId, trade.getGoodsId());
            goodsWrapper.eq(SecondGoodsRecord::getGoodsStatus, "3");
            goodsWrapper.orderByDesc(SecondGoodsRecord::getCreatedTime);
            goodsWrapper.last(" limit 1 ");
            SecondGoodsRecord goodsRecord = secondGoodsRecordMapper.selectOne(goodsWrapper);
            if (null != goodsRecord) trade.setGoodsRecordId(goodsRecord.getId());
            // 保存交易记录
            secondTradeRecordMapper.insert(trade);

            // 保存交易操作表
            SecondTradeOperation operation = new SecondTradeOperation();
            operation.setTradeId(trade.getId());
            operation.setUserId(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId"));
            operation.setType(1);
            operation.setCreatedTime(new Date());
            secondTradeOperationMapper.insert(operation);

            // 商品更新交易id
            SecondGoods goods = new SecondGoods();
            goods.setId(trade.getGoodsId());
            goods.setTradeId(trade.getId());
            secondGoodsMapper.updateById(goods);

            // 查询商品
            goods = secondGoodsMapper.selectById(trade.getGoodsId());

            if (StringUtils.isNotBlank(trade.getEntrustUserPhone()) && StringUtils.isNotBlank(trade.getEntrustUserName()) && StringUtils.isNotBlank(trade.getEntrustIdCard())) {
                // 添加商家委托信息
                SecondEntrustUser secondEntrustUser = new SecondEntrustUser();
                secondEntrustUser.setEntrustTradeId(trade.getId());
                secondEntrustUser.setEntrustUserPhone(trade.getEntrustUserPhone());
                secondEntrustUser.setEntrustUserName(trade.getEntrustUserName());
                secondEntrustUser.setEntrustIdCard(trade.getEntrustIdCard());
                secondEntrustUser.setEntrustTradeNo(trade.getTradeNo());
                secondEntrustUser.setEntrustIdCardImg(trade.getEntrustIdCardImg());
                secondEntrustUserMapper.insert(secondEntrustUser);
            }

            // 发送消息
            sendMsg(goods, trade, 1, "4");

            return true;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.createTrade(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    /**
     * 发送消息
     * @param goods        商品信息
     * @param trade        交易信息
     * @param tradeStatus  1-待确认  2-已拒绝  3-待交易  6-交易取消
     * @param messageType  4-二手交易创建/确认/拒绝/取消  5-二手交易签到提醒  6-二手交易已签到
     */
    @Transactional(rollbackFor = Exception.class)
    public void sendMsg(SecondGoods goods, SecondTradeRecord trade, Integer tradeStatus, String messageType) {
        // 封装交易信息
        JSONObject message = new JSONObject();
        message.put("title", goods.getTitle());
        message.put("goodsId", goods.getId());
        message.put("homeImage", goods.getHomeImage());
        message.put("tradeId", trade.getId());
        message.put("transactionAmount", trade.getTransactionAmount());
        message.put("transactionLatitudeLongitude", trade.getTransactionLatitudeLongitude());
        message.put("transactionLatitudeLongitudeAddress", trade.getTransactionLatitudeLongitudeAddress());
        message.put("transactionLocation", trade.getTransactionLocation());
        message.put("transactionTime", trade.getTransactionTime());
        message.put("tradeStatus", tradeStatus);

        // 查询商家委托信息
        LambdaQueryWrapper<SecondEntrustUser> entrustWrapper = new LambdaQueryWrapper<>();
        entrustWrapper.eq(SecondEntrustUser::getEntrustTradeId, trade.getId());
        SecondEntrustUser entrustUser = secondEntrustUserMapper.selectOne(entrustWrapper);
        if ( entrustUser != null ) {
            message.put("entrustId", entrustUser.getId());
            message.put("entrustUserPhone", entrustUser.getEntrustUserPhone());
            message.put("entrustUserName", entrustUser.getEntrustUserName());
            message.put("entrustIdCard", entrustUser.getEntrustIdCard());
            message.put("entrustIdCardImg", entrustUser.getEntrustIdCardImg());
        }

        if (6 == tradeStatus) {
            message.put("cancelUserId", trade.getCancelUserId());
            message.put("cancelReason", trade.getCancelReason());
            message.put("cancelReasonSupplement", trade.getCancelReasonSupplement());

            // 查询字典表
            LambdaQueryWrapper<StoreDictionary> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StoreDictionary::getTypeName, "cancelTradeReason");
            wrapper.eq(StoreDictionary::getDictId, trade.getCancelReason());
            StoreDictionary storeDictionary = storeDictionaryMapper.selectOne(wrapper);
            message.put("cancelReasonName", null == storeDictionary ? "" : storeDictionary.getDictDetail());
        }

        // 发起交易人信息
        Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
        String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");

        // 获取交易对方信息
        LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
        String receiverId = "user_" + lifeUser.getUserPhone();

        // 消息
        LifeMessage lifeMessage = new LifeMessage();
        lifeMessage.setSenderId(phoneId);
        lifeMessage.setReceiverId(receiverId);
        lifeMessage.setType(messageType);
        lifeMessage.setContent(message.toJSONString());
        lifeMessageUtil.fillUserTypeAndRefId(lifeMessage);
        lifeMessageMapper.insert(lifeMessage);
        message.put("createdTime", lifeMessage.getCreatedTime());

        // 给买家与卖家发送交易消息
        WebSocketVo webSocketVo = new WebSocketVo();
        webSocketVo.setSenderId(phoneId);
        webSocketVo.setReceiverId(receiverId);
        webSocketVo.setCategory("message");
        webSocketVo.setType(messageType);
        webSocketVo.setIsRead(0);
        webSocketVo.setText(message.toJSONString());
        webSocketVo.setMessageId(lifeMessage.getId());

        alienStoreFeign.sendMsgToClientByPhoneId(phoneId, JSONObject.from(webSocketVo).toJSONString());
        alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());
    }

    @Override
    public boolean goodsTradeConfirm(int goodsId) throws Exception {
        try {
            LambdaQueryWrapper<SecondTradeRecord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SecondTradeRecord::getGoodsId, goodsId);
            queryWrapper.in(SecondTradeRecord::getTradeStatus, 3, 4);
            return secondTradeRecordMapper.selectCount(queryWrapper) == 0;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.goodsTrade(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean tradeConfirm(int tradeId, int messageId, int type) throws BusinessException, Exception {
        try {
            // 交易信息
            SecondTradeRecord trade = secondTradeRecordMapper.selectById(tradeId);

            // 判断商品是否正在交易中
            if (type == 1) {
                LambdaQueryWrapper<SecondTradeRecord> recordWrapper = new LambdaQueryWrapper<>();
                recordWrapper.eq(SecondTradeRecord::getGoodsId, trade.getGoodsId());
                recordWrapper.eq(SecondTradeRecord::getTradeStatus, 3);
                if (secondTradeRecordMapper.selectCount(recordWrapper) > 0) {
                    throw new BusinessException("该商品正在交易中");
                }
            }

            // 有定时任务: 超过交易时间还未确认的交易会自动取消并保存交易操作表  所以如果是已取消的交易  不需要进行这两步操作
            if (trade.getTradeStatus() != 6) {
                // 修改交易状态
                SecondTradeRecord tradeRecord = new SecondTradeRecord();
                tradeRecord.setId(tradeId);
                tradeRecord.setTradeStatus(type == 1 ? 3 : 2);
                secondTradeRecordMapper.updateById(tradeRecord);

                // 保存交易操作表
                SecondTradeOperation operation = new SecondTradeOperation();
                operation.setTradeId(trade.getId());
                operation.setUserId(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId"));
                operation.setType(type == 1 ? 3 : 2);
                secondTradeOperationMapper.insert(operation);
            }

            // 商品信息
            SecondGoods goods = secondGoodsMapper.selectById(trade.getGoodsId());

            // 修改待确认的消息
            LifeMessage lastMessage = lifeMessageMapper.selectById(messageId);

            JSONObject lastMessageContent = JSONObject.parseObject(lastMessage.getContent());
            lastMessageContent.put("messageId", lastMessage.getId());
            lastMessageContent.put("tradeStatus", trade.getTradeStatus() == 6 ? 6 : (type == 1 ? 3 : 2));
            LifeMessage message = new LifeMessage();
            message.setId(lastMessage.getId());
            message.setContent(lastMessageContent.toJSONString());
            lifeMessageMapper.updateById(message);

            // 如果交易已取消  不需要发送消息
            if (trade.getTradeStatus() != 6) {
                // 发送消息
                trade.setTradeStatus(type == 1 ? 3 : 2);
                sendMsg(goods, trade, trade.getTradeStatus(), "4");
            }

            // 发起交易人信息
            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");

            // 获取交易对方信息
            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
            String receiverId = "user_" + lifeUser.getUserPhone();

            // 给买家与卖家发送交易消息
            WebSocketVo webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId(phoneId);
            webSocketVo.setReceiverId(receiverId);
            webSocketVo.setCategory("message");
            webSocketVo.setType("4");
            webSocketVo.setIsRead(0);
            webSocketVo.setText(lastMessageContent.toJSONString());
            webSocketVo.setMessageId(lastMessage.getId());

            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, JSONObject.from(webSocketVo).toJSONString());
            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());

            // 交易已取消
            if (trade.getTradeStatus() == 6 ) {
                throw new BusinessException("该交易已取消,不可操作");
            }

            // 创建交易时间小于十分钟,直接发送交易提醒
            if (1 == type && Math.abs(Duration.between(Instant.now(), trade.getTransactionTime().toInstant()).getSeconds()) < 600) {
                sendSignInMessage(trade);
            }

            // 风控机制 - 高频高价交易
            LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SecondTradeRecord::getSellerId, trade.getSellerId());
            wrapper.in(SecondTradeRecord::getTradeStatus, "3, 4");
            wrapper.between(SecondTradeRecord::getTransactionTime,
                    trade.getTransactionTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() + " 00:00:00",
                    trade.getTransactionTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() + " 23:59:59");
            wrapper.gt(SecondTradeRecord::getTransactionAmount, riskControlProperties.getMoneyLaundering().getAmountThreshold());
            List<SecondTradeRecord> recordList = secondTradeRecordMapper.selectList(wrapper);
            if (recordList.size() > riskControlProperties.getMoneyLaundering().getDailyCount()) {
                String startDate = LocalDateTime.now().minusHours(24L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                String endDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                List<SecondUserCreditRecord> num = secondUserCreditRecordMapper.selectList(new LambdaQueryWrapper<SecondUserCreditRecord>()
                        .eq(SecondUserCreditRecord::getUserId, trade.getSellerId())
                        .eq(SecondUserCreditRecord::getPointsType, SecondUserCreditScoreEnum.SUSPECTED_OF_MONEY_LAUNDERING.getCode())
                        .ge(SecondUserCreditRecord::getCreatedTime, startDate)
                        .le(SecondUserCreditRecord::getCreatedTime, endDate));
                if (num.size() <= 0) {
                    LambdaQueryWrapper<SecondUserCredit> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(SecondUserCredit::getUserId, trade.getSellerId())
                            .orderByDesc(SecondUserCredit::getCreatedTime).last("LIMIT 1");
                    SecondUserCredit secondUserCredit = secondUserCreditMapper.selectOne(queryWrapper);
                    int score = secondUserCredit.getUserPoints() + SecondUserCreditScoreEnum.SUSPECTED_OF_MONEY_LAUNDERING.getScore();
                    secondUserCredit.setUserPoints(score);
                    secondUserCreditMapper.updateById(secondUserCredit);

                    SecondUserCreditRecord record = new SecondUserCreditRecord();
                    record.setUserId(trade.getSellerId());
                    record.setPointsType(SecondUserCreditScoreEnum.SUSPECTED_OF_MONEY_LAUNDERING.getCode());
                    record.setPoints(SecondUserCreditScoreEnum.SUSPECTED_OF_MONEY_LAUNDERING.getScore());
                    record.setCurrentScoreCount(score);
                    record.setCreatedTime(new Date());
                    secondUserCreditRecordMapper.insert(record);

                    // 小于100分封禁用户
                    if (score < 100) {
                        LifeUser user = new LifeUser();
                        user.setId(trade.getSellerId());
                        user.setIsBanned(1);
                        lifeUserMapper.updateById(user);
                    }
                }

//                SecondRiskControlRecord riskControlRecord = new SecondRiskControlRecord();
//                riskControlRecord.setRuleType(1);
//                riskControlRecord.setUserId(trade.getSellerId());
//                riskControlRecord.setBusinessId(String.valueOf(trade.getSellerId()));
//                riskControlRecord.setRuleName(riskControlProperties.getMoneyLaundering().getRiskType());
//                JSONArray detailInfo = new JSONArray();
//                detailInfo.addAll(recordList.stream().map(SecondTradeRecord::getId).collect(Collectors.toList()));
//                riskControlRecord.setDetailInfo(detailInfo.toJSONString());
//                secondRiskControlRecordMapper.insert(riskControlRecord);
            }

            return true;
        } catch (BusinessException e) {
            throw new BusinessException(e);
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.tradeConfirm(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelTrade(int tradeId, String cancelReason, String cancelReasonSupplement) throws Exception {
        try {
            // 发起交易人信息
            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");

            // 修改交易状态
            SecondTradeRecord tradeRecord = new SecondTradeRecord();
            tradeRecord.setId(tradeId);
            tradeRecord.setTradeStatus(6);
            tradeRecord.setCancelUserId(userId);
            tradeRecord.setCancelReason(cancelReason);
            tradeRecord.setCancelReasonSupplement(cancelReasonSupplement);
            secondTradeRecordMapper.updateById(tradeRecord);

            // 保存交易操作表
            SecondTradeOperation operation = new SecondTradeOperation();
            operation.setTradeId(tradeId);
            operation.setUserId(Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId"));
            operation.setType(7);
            operation.setCreatedTime(new Date());
            secondTradeOperationMapper.insert(operation);

            // 交易信息
            SecondTradeRecord trade = secondTradeRecordMapper.selectById(tradeId);

            // 发送消息
            sendMsg(secondGoodsMapper.selectById(trade.getGoodsId()), trade, 6, "4");

            return true;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.cancelTrade(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    @Override
    public boolean whetherCanSignIn(int tradeId) throws Exception {
        try {
            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            SecondTradeRecord trade = secondTradeRecordMapper.selectById(tradeId);
            if (null == trade) return false;

            if (userId == trade.getBuyerId() && 0 == trade.getBuyerSignIn()) return true;
            if (userId == trade.getSellerId() && 0 == trade.getSellerSignIn()) return true;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.whetherCanSignIn(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean tradeSignIn(int tradeId, int messageId, String signInLatitudeLongitude, String signInLatitudeLongitudeAddress) throws BusinessException, Exception {
        try {
            SecondTradeRecord trade = secondTradeRecordMapper.selectById(tradeId);
            if (null == trade) return false;
            if (trade.getTradeStatus() != 3) return false;

            // 发起交易人信息
            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");

            // 获取交易对方信息
            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
            String receiverId = "user_" + lifeUser.getUserPhone();

            // 保存交易签到信息
            SecondTradeRecord record = new SecondTradeRecord();
            record.setId(tradeId);
            Date now = Date.from(LocalDateTime.now().withSecond(0).withNano(0).atZone(ZoneId.systemDefault()).toInstant());
            if (userId == trade.getBuyerId()) {
                if (1 == trade.getBuyerSignIn()) throw new BusinessException("该交易已签到,无需再次签到");
                record.setBuyerSignIn(1);
                record.setBuyerSignInTime(now);
                record.setBuyerSignInLatitudeLongitude(signInLatitudeLongitude);
                record.setBuyerSignInLatitudeLongitudeAddress(signInLatitudeLongitudeAddress);
            } else if (userId == trade.getSellerId()) {
                if (1 == trade.getSellerSignIn()) throw new BusinessException("该交易已签到,无需再次签到");
                record.setSellerSignIn(1);
                record.setSellerSignInTime(now);
                record.setSellerSignInLatitudeLongitude(signInLatitudeLongitude);
                record.setSellerSignInLatitudeLongitudeAddress(signInLatitudeLongitudeAddress);
            } else {
                log.error("SecondTradeRecordServiceImpl.tradeSignIn(): Error Msg={}", "userId无效");
                throw new Exception();
            }
            secondTradeRecordMapper.updateById(record);

            // 保存交易操作表
            SecondTradeOperation operation = new SecondTradeOperation();
            operation.setTradeId(tradeId);
            operation.setUserId(userId);
            operation.setType(4);
            operation.setCreatedTime(new Date());
            secondTradeOperationMapper.insert(operation);

            // 删除签到提醒消息
            LifeMessage signInMessage = lifeMessageMapper.selectById(messageId);
            if (null == signInMessage) throw new BusinessException("该交易已签到,无需再次签到");
            lifeMessageMapper.deleteById(messageId);

            // 发送已签到消息
            JSONObject messageContent = JSONObject.parseObject(signInMessage.getContent());
            messageContent.put("tradeId", tradeId);
            messageContent.put("signInTime", now.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
            messageContent.put("signInLatitudeLongitude", signInLatitudeLongitude);
            messageContent.put("signInLatitudeLongitudeAddress", signInLatitudeLongitudeAddress);
            LifeMessage message = new LifeMessage();
            message.setSenderId(phoneId);
            message.setReceiverId(receiverId);
            message.setContent(messageContent.toJSONString());
            message.setType("6");
            lifeMessageUtil.fillUserTypeAndRefId(message);
            lifeMessageMapper.insert(message);

            // 推送已签到消息
            WebSocketVo webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId(phoneId);
            webSocketVo.setReceiverId(receiverId);
            webSocketVo.setCategory("message");
            webSocketVo.setType("6");
            webSocketVo.setIsRead(0);
            webSocketVo.setText(messageContent.toJSONString());
            webSocketVo.setMessageId(message.getId());

            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, JSONObject.from(webSocketVo).toJSONString());
            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());

            return true;
        } catch (BusinessException e) {
            throw new BusinessException(e);
        }  catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.tradeSignIn(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SecondTradeRecordVo getUserTradeStatus(int tradeId) throws Exception {
        try {
            SecondTradeRecordVo recordVo = new SecondTradeRecordVo();
            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            SecondTradeRecord tradeRecord = secondTradeRecordMapper.selectById(tradeId);
            if (null == tradeRecord) return new SecondTradeRecordVo();

            if (userId == tradeRecord.getBuyerId()) {
                recordVo.setUserTransactionStatus(tradeRecord.getBuyerTransactionStatus());
                recordVo.setUserEvaluate(tradeRecord.getBuyerEvaluate());
                recordVo.setUserRating(tradeRecord.getBuyerRating());
            } else if (userId == tradeRecord.getSellerId()) {
                recordVo.setUserTransactionStatus(tradeRecord.getSellerTransactionStatus());
                recordVo.setUserEvaluate(tradeRecord.getSellerEvaluate());
                recordVo.setUserRating(tradeRecord.getSellerRating());
            }
            recordVo.setSellerId(tradeRecord.getSellerId());
            return recordVo;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.getUserTradeStatus(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean tradeCompleteConfirm(int tradeId, int type, String evaluate, Integer rating) throws Exception {
        try {
            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            SecondTradeRecord tradeRecord = secondTradeRecordMapper.selectById(tradeId);
            SecondTradeRecord record = new SecondTradeRecord();
            record.setId(tradeId);
            // 买家
            if (userId == tradeRecord.getBuyerId()) {
                if (0 != tradeRecord.getBuyerTransactionStatus()) return false;
                record.setBuyerTransactionStatus(type);
                record.setBuyerCompleteTime(new Date());
                record.setBuyerEvaluate(evaluate);
                record.setBuyerRating(rating);
            // 卖家
            } else if (userId == tradeRecord.getSellerId()) {
                if (0 != tradeRecord.getSellerTransactionStatus()) return false;
                record.setSellerTransactionStatus(type);
                record.setSellerCompleteTime(new Date());
                record.setSellerEvaluate(evaluate);
                record.setSellerRating(rating);
                record.setTradeStatus(1 == type ? 4 : 5);
                // 卖家如果选择交易成功  同步修改商品表
                if (1 == type) {
                    SecondGoods goods = new SecondGoods();
                    goods.setId(tradeRecord.getGoodsId());
                    goods.setGoodsStatus(5);
                    secondGoodsMapper.updateById(goods);
                }
            } else {
                return false;
            }
            secondTradeRecordMapper.updateById(record);

            // 保存交易操作表
            SecondTradeOperation operation = new SecondTradeOperation();
            operation.setTradeId(tradeId);
            operation.setUserId(userId);
            operation.setType(1 == type ? 5 : 6);
            operation.setCreatedTime(new Date());
            secondTradeOperationMapper.insert(operation);

            // 添加信用分
            if (1 == type && userId == tradeRecord.getSellerId()) {
                creditScore(tradeRecord.getBuyerId());
                creditScore(tradeRecord.getSellerId());
            }

            return true;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.tradeCompleteConfirm(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    /**
     * 增加交易信用分
     * @param userId 用户id
     */
    private void creditScore(Integer userId) {
        LambdaQueryWrapper<SecondUserCreditRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SecondUserCreditRecord::getUserId, userId);
        wrapper.eq(SecondUserCreditRecord::getPointsType, 3);
        List<SecondUserCreditRecord> records = secondUserCreditRecordMapper.selectList(wrapper);
        int userPoints = records.stream().mapToInt(SecondUserCreditRecord::getPoints).sum();

        if (userPoints < 500) {
            // 使用数据库原子操作更新积分
            secondUserCreditMapper.updatePointsByUserId(userId, 10);

            // 查询最新的积分值
            LambdaQueryWrapper<SecondUserCredit> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SecondUserCredit::getUserId, userId);
            SecondUserCredit userCredit = secondUserCreditMapper.selectOne(queryWrapper);

            if (userCredit != null) {
                SecondUserCreditRecord record = new SecondUserCreditRecord();
                record.setUserId(userId);
                record.setPoints(10);
                record.setPointsType(3);
                record.setCurrentScoreCount(userCredit.getUserPoints()); // 注意：这里应该是更新后的积分
                secondUserCreditRecordMapper.insert(record);
            }
        }
    }


    @Override
    public List<SecondTradeRecordVo> getTradeRecord(int sideId) throws Exception {
        try {
            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            QueryWrapper<SecondTradeRecord> wrapper = new QueryWrapper<>();
            wrapper.eq("trade.delete_flag", 0);
            wrapper.apply("((trade.buyer_id = '" + sideId + "' and trade.seller_id = '" + userId + "') || (trade.buyer_id = '" + userId + "' and trade.seller_id = '" + sideId + "'))");
            wrapper.orderByDesc("trade.created_time");
            List<SecondTradeRecordVo> vo = secondTradeRecordMapper.getTradeRecord(wrapper);
            if (vo.size() > 0) {
                for (SecondTradeRecordVo item : vo) {
                    // 查询商家委托信息
                    LambdaQueryWrapper<SecondEntrustUser> entrustWrapper = new LambdaQueryWrapper<>();
                    entrustWrapper.eq(SecondEntrustUser::getEntrustTradeId, item.getId());
                    SecondEntrustUser entrustUser = secondEntrustUserMapper.selectOne(entrustWrapper);
                    if ( entrustUser != null ) {
                        item.setEntrustId(entrustUser.getId());
                        item.setEntrustUserPhone(entrustUser.getEntrustUserPhone());
                        item.setEntrustUserName(entrustUser.getEntrustUserName());
                        item.setEntrustIdCard(entrustUser.getEntrustIdCard());
                        item.setEntrustIdCardImg(entrustUser.getEntrustIdCardImg());
                    }
                }
            }
            return vo;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.getTradeRecord(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    @Override
    public SecondTradeRecord hasInTradeRecord(Integer sideId) throws Exception {
        try {
            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SecondTradeRecord::getTradeStatus, 3);
            wrapper.apply("((seller_id = " + userId + " and buyer_id = " + sideId + ") or " +
                    "(seller_id = " + sideId + " and buyer_id = " + userId + "))");
            wrapper.orderByAsc(SecondTradeRecord::getTransactionTime);
            List<SecondTradeRecord> list = secondTradeRecordMapper.selectList(wrapper);
            if (list.isEmpty()) return null;

            // 取出所有的交易时间
            List<Date> dates = list.stream().map(SecondTradeRecord::getTransactionTime).collect(Collectors.toList());
            if (dates.isEmpty()) return null;

            // 取出距离当前时间最近的交易时间
            Date now = new Date();
            Date minDate = dates.stream()
                    .min(Comparator.comparingLong(date ->
                            Math.abs(date.getTime() - now.getTime())))
                    .orElse(null);

            list = list.stream().filter(item -> item.getTransactionTime().equals(minDate)).collect(Collectors.toList());
            return list.isEmpty() ? null : (1 == list.get(0).getBuyerSignIn() && 1 == list.get(0).getSellerSignIn() ? null : list.get(0));
         } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.hasInTradeRecord(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean modifyTradeRecord(int type, Integer tradeId, String transactionTime, String transactionLatitudeLongitude, String transactionLatitudeLongitudeAddress, String transactionLocation, String messageId,
                                     String userPhone, String userName, String idCard, Integer entrustId, String idCardImg) throws Exception {
        try {
            if (type == 1) {
                LambdaUpdateWrapper<SecondTradeRecord> wrapper = new LambdaUpdateWrapper<>();
                wrapper.set(SecondTradeRecord::getTransactionTime, transactionTime);
                wrapper.set(SecondTradeRecord::getTransactionLatitudeLongitude, transactionLatitudeLongitude);
                wrapper.set(SecondTradeRecord::getTransactionLatitudeLongitudeAddress, transactionLatitudeLongitudeAddress);
                wrapper.set(SecondTradeRecord::getTransactionLocation, transactionLocation);
                // 清空签到信息
                wrapper.set(SecondTradeRecord::getBuyerSignIn, 0);
                wrapper.set(SecondTradeRecord::getBuyerSignInTime, null);
                wrapper.set(SecondTradeRecord::getBuyerSignInLatitudeLongitude, null);
                wrapper.set(SecondTradeRecord::getBuyerSignInLatitudeLongitudeAddress, null);
                wrapper.set(SecondTradeRecord::getSellerSignIn, 0);
                wrapper.set(SecondTradeRecord::getSellerSignInTime, null);
                wrapper.set(SecondTradeRecord::getSellerSignInLatitudeLongitude, null);
                wrapper.set(SecondTradeRecord::getSellerSignInLatitudeLongitudeAddress, null);
                wrapper.eq(SecondTradeRecord::getId, tradeId);
                secondTradeRecordMapper.update(null, wrapper);
            }
            // 修改待确认的消息
            LifeMessage lastMessage = lifeMessageMapper.selectById(messageId);

            JSONObject lastMessageContent = JSONObject.parseObject(lastMessage.getContent());
            lastMessageContent.put("messageId", lastMessage.getId());
            lastMessageContent.put("modifyStatus", type == 1 ? 3 : 2);
            LifeMessage message = new LifeMessage();
            message.setId(lastMessage.getId());
            message.setContent(lastMessageContent.toJSONString());
            lifeMessageMapper.updateById(message);

            SecondTradeRecord trade = secondTradeRecordMapper.selectById(tradeId);

            // 发起交易人信息
            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");

            // 获取交易对方信息
            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
            String receiverId = "user_" + lifeUser.getUserPhone();

            if (entrustId != null) {
                LambdaUpdateWrapper<SecondEntrustUser> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(SecondEntrustUser::getId, entrustId);
                if (StringUtils.isBlank(userPhone) && StringUtils.isBlank(userName) && StringUtils.isBlank(idCard)) {
                    updateWrapper.set(SecondEntrustUser::getDeleteFlag, 1);
                } else {
                    updateWrapper.set(SecondEntrustUser::getEntrustTradeId, tradeId);
                    updateWrapper.set(SecondEntrustUser::getEntrustUserPhone, userPhone);
                    updateWrapper.set(SecondEntrustUser::getEntrustUserName, userName);
                    updateWrapper.set(SecondEntrustUser::getEntrustIdCard, idCard);
                    updateWrapper.set(SecondEntrustUser::getEntrustIdCardImg, idCardImg);
                }
                secondEntrustUserMapper.update(null, updateWrapper);
            } else {
                LambdaUpdateWrapper<SecondEntrustUser> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(SecondEntrustUser::getEntrustTradeId, tradeId);
                Integer entrust = secondEntrustUserMapper.selectCount(wrapper);
                if (entrust <= 0) {
                    if (StringUtils.isNotBlank(userPhone) && StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(idCard)) {
                        secondEntrustUserMapper.insert(new SecondEntrustUser()
                                .setEntrustTradeId(tradeId)
                                .setEntrustUserPhone(userPhone)
                                .setEntrustUserName(userName)
                                .setEntrustIdCard(idCard)
                                .setEntrustIdCardImg(idCardImg)
                                .setDeleteFlag(0));
                    }
                }
            }


            // 给买家与卖家发送交易消息
            WebSocketVo webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId(phoneId);
            webSocketVo.setReceiverId(receiverId);
            webSocketVo.setCategory("message");
            webSocketVo.setType("9");
            webSocketVo.setIsRead(0);
            webSocketVo.setText(lastMessageContent.toJSONString());
            webSocketVo.setMessageId(lastMessage.getId());

            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, JSONObject.from(webSocketVo).toJSONString());
            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());

            // 交易时间小于十分钟,直接发送交易提醒
            if (1 == type && Math.abs(Duration.between(Instant.now(), trade.getTransactionTime().toInstant()).getSeconds()) < 600) {
                sendSignInMessage(trade);
            }
            return true;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.modifyTradeRecord(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    private void sendSignInMessage(SecondTradeRecord tradeRecord) throws Exception {
        log.info("二手交易平台-创建交易时间小于十分钟,直接发送交易提醒---sendSignInMessage()---");
        try {
            LifeUser buyer = lifeUserMapper.selectById(tradeRecord.getBuyerId());
            LifeUser seller = lifeUserMapper.selectById(tradeRecord.getSellerId());

            String buyerPhoneId = null == buyer ? "" : "user_" + buyer.getUserPhone();
            String sellerPhoneId = null == seller ? "" : "user_" + seller.getUserPhone();

            // 封装交易信息
            JSONObject message = new JSONObject();
            message.put("tradeId", tradeRecord.getId());
            message.put("transactionAmount", tradeRecord.getTransactionAmount());
            message.put("transactionLatitudeLongitude", tradeRecord.getTransactionLatitudeLongitude());
            message.put("transactionLatitudeLongitudeAddress", tradeRecord.getTransactionLatitudeLongitudeAddress());
            message.put("transactionLocation", tradeRecord.getTransactionLocation());
            message.put("transactionTime", tradeRecord.getTransactionTime());
            message.put("tradeStatus", tradeRecord.getTradeStatus());

            // 给买家发送消息
            LifeMessage lifeMessage = new LifeMessage();
            lifeMessage.setSenderId(sellerPhoneId);
            lifeMessage.setReceiverId(buyerPhoneId);
            lifeMessage.setContent(message.toJSONString());
            lifeMessage.setType("5");
            lifeMessageUtil.fillUserTypeAndRefId(lifeMessage);
            lifeMessageMapper.insert(lifeMessage);

            // 给买家推送消息
            WebSocketVo webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId(sellerPhoneId);
            webSocketVo.setReceiverId(buyerPhoneId);
            webSocketVo.setCategory("message");
            webSocketVo.setType("5");
            webSocketVo.setText(message.toJSONString());
            webSocketVo.setMessageId(lifeMessage.getId());
            alienStoreFeign.sendMsgToClientByPhoneId(buyerPhoneId, JSONObject.from(webSocketVo).toJSONString());

            // 给买家发送通知
            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setSenderId("system");
            lifeNotice.setReceiverId(buyerPhoneId);
            lifeNotice.setBusinessId(tradeRecord.getId());
            lifeNotice.setTitle("商品交易签到");
            lifeNotice.setNoticeType(1);
            // 封装通知信息
            JSONObject noticeMessage = new JSONObject();
            noticeMessage.put("tradeId", tradeRecord.getId());
            noticeMessage.put("otherSideUserId", tradeRecord.getSellerId());
            noticeMessage.put("otherSidePhoneId", sellerPhoneId);
            noticeMessage.put("otherSideName", null == seller ? "" : seller.getUserName());
            noticeMessage.put("otherSideImage", null == seller ? "" : seller.getUserImage());
            noticeMessage.put("message", "您有一笔交易即将开始, 请及时前往查看");
            lifeNotice.setContext(noticeMessage.toJSONString());
            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            lifeNoticeMapper.insert(lifeNotice);

            // 给买家推送通知
            webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId("system");
            webSocketVo.setReceiverId(buyerPhoneId);
            webSocketVo.setCategory("notice");
            webSocketVo.setNoticeType("1");
            webSocketVo.setType("5");
            webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
            webSocketVo.setMessageId(lifeMessage.getId());
            alienStoreFeign.sendMsgToClientByPhoneId(buyerPhoneId, JSONObject.from(webSocketVo).toJSONString());

            // 给卖家发送消息
            lifeMessage = new LifeMessage();
            lifeMessage.setSenderId(buyerPhoneId);
            lifeMessage.setReceiverId(sellerPhoneId);
            lifeMessage.setContent(message.toJSONString());
            lifeMessage.setType("5");
            lifeMessageUtil.fillUserTypeAndRefId(lifeMessage);
            lifeMessageMapper.insert(lifeMessage);

            // 给卖家推送消息
            webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId(buyerPhoneId);
            webSocketVo.setReceiverId(sellerPhoneId);
            webSocketVo.setCategory("message");
            webSocketVo.setType("5");
            webSocketVo.setText(message.toJSONString());
            webSocketVo.setMessageId(lifeMessage.getId());
            alienStoreFeign.sendMsgToClientByPhoneId(sellerPhoneId, JSONObject.from(webSocketVo).toJSONString());

            // 给卖家发送通知
            lifeNotice = new LifeNotice();
            lifeNotice.setSenderId("system");
            lifeNotice.setReceiverId(sellerPhoneId);
            lifeNotice.setBusinessId(tradeRecord.getId());
            lifeNotice.setTitle("商品交易签到");
            lifeNotice.setNoticeType(1);
            // 封装通知信息
            noticeMessage = new JSONObject();
            noticeMessage.put("tradeId", tradeRecord.getId());
            noticeMessage.put("otherSideUserId", tradeRecord.getBuyerId());
            noticeMessage.put("otherSidePhoneId", buyerPhoneId);
            noticeMessage.put("otherSideName", null == buyer ? "" : buyer.getUserName());
            noticeMessage.put("otherSideImage", null == buyer ? "" : buyer.getUserImage());
            noticeMessage.put("message", "您有一笔交易即将开始, 请及时前往查看");
            lifeNotice.setContext(noticeMessage.toJSONString());
            lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
            lifeNoticeMapper.insert(lifeNotice);

            // 给卖家推送通知
            webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId("system");
            webSocketVo.setReceiverId(sellerPhoneId);
            webSocketVo.setCategory("notice");
            webSocketVo.setNoticeType("1");
            webSocketVo.setType("5");
            webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
            webSocketVo.setMessageId(lifeMessage.getId());
            alienStoreFeign.sendMsgToClientByPhoneId(sellerPhoneId, JSONObject.from(webSocketVo).toJSONString());
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.sendSignInMessage(): Error Msg={}", e.getMessage());
            throw new Exception(e);
        }
    }

    /**
     * 获取用户作为卖家的交易评价列表（分页）
     *
     * @param sellerId 卖家ID（用户ID，必传）
     * @param pageNum 页码
     * @param pageSize 每页条数
     * @return 卖家评价分页列表
     */
    @Override
    public IPage<SellerEvaluationVo> getSellerEvaluationList(Integer sellerId, Integer pageNum, Integer pageSize) throws Exception {
        try {
            log.info("SecondTradeRecordServiceImpl.getSellerEvaluationList(): sellerId={}, pageNum={}, pageSize={}", 
                    sellerId, pageNum, pageSize);
            
            // sellerId必传校验
            if (sellerId == null) {
                throw new Exception("卖家ID不能为空");
            }
            
            // 参数默认值处理
            if (pageNum == null || pageNum < 1) {
                pageNum = 1;
            }
            if (pageSize == null || pageSize < 1) {
                pageSize = 10;
            }
            // 限制最大每页条数
            if (pageSize > 100) {
                pageSize = 100;
            }
            
            // 使用MyBatis Plus分页查询交易记录
            Page<SecondTradeRecord> page = new Page<>(pageNum, pageSize);
            LambdaQueryWrapper<SecondTradeRecord> tradeWrapper = new LambdaQueryWrapper<>();
            tradeWrapper.eq(SecondTradeRecord::getSellerId, sellerId)
                    .eq(SecondTradeRecord::getDeleteFlag, 0)
                    .isNotNull(SecondTradeRecord::getBuyerEvaluate)
                    .ne(SecondTradeRecord::getBuyerEvaluate, "")
                    .orderByDesc(SecondTradeRecord::getCreatedTime);
            
            IPage<SecondTradeRecord> tradePage = secondTradeRecordMapper.selectPage(page, tradeWrapper);
            List<SecondTradeRecord> tradeRecords = tradePage.getRecords();
            
            // 如果没有数据，直接返回空分页对象
            if (tradeRecords.isEmpty()) {
                log.info("SecondTradeRecordServiceImpl.getSellerEvaluationList(): 未查询到评价记录");
                Page<SellerEvaluationVo> emptyPage = new Page<>(pageNum, pageSize);
                emptyPage.setTotal(0);
                return emptyPage;
            }
            
            // 获取所有商品记录ID、买家ID和卖家ID
            List<Integer> goodsRecordIds = tradeRecords.stream()
                    .map(SecondTradeRecord::getGoodsRecordId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            List<Integer> buyerIds = tradeRecords.stream()
                    .map(SecondTradeRecord::getBuyerId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            // 批量查询商品记录信息
            java.util.Map<Integer, SecondGoodsRecord> goodsRecordMap = new java.util.HashMap<>();
            if (!goodsRecordIds.isEmpty()) {
                LambdaQueryWrapper<SecondGoodsRecord> goodsWrapper = new LambdaQueryWrapper<>();
                goodsWrapper.in(SecondGoodsRecord::getId, goodsRecordIds);
                List<SecondGoodsRecord> goodsRecords = secondGoodsRecordMapper.selectList(goodsWrapper);
                goodsRecordMap = goodsRecords.stream()
                        .collect(Collectors.toMap(SecondGoodsRecord::getId, g -> g));
            }
            
            // 批量查询买家用户信息
            java.util.Map<Integer, LifeUser> buyerMap = new java.util.HashMap<>();
            if (!buyerIds.isEmpty()) {
                LambdaQueryWrapper<LifeUser> userWrapper = new LambdaQueryWrapper<>();
                userWrapper.in(LifeUser::getId, buyerIds)
                        .eq(LifeUser::getDeleteFlag, 0);
                List<LifeUser> buyers = lifeUserMapper.selectList(userWrapper);
                buyerMap = buyers.stream()
                        .collect(Collectors.toMap(LifeUser::getId, u -> u));
            }
            
            // 查询卖家信息
            LifeUser seller = lifeUserMapper.selectById(sellerId);
            
            // 批量查询买家和卖家的信用积分
            List<Integer> allUserIds = new java.util.ArrayList<>(buyerIds);
            allUserIds.add(sellerId);
            java.util.Map<Integer, SecondUserCredit> creditMap = new java.util.HashMap<>();
            if (!allUserIds.isEmpty()) {
                LambdaQueryWrapper<SecondUserCredit> creditWrapper = new LambdaQueryWrapper<>();
                creditWrapper.in(SecondUserCredit::getUserId, allUserIds)
                        .eq(SecondUserCredit::getDeleteFlag, 0);
                List<SecondUserCredit> credits = secondUserCreditMapper.selectList(creditWrapper);
                creditMap = credits.stream()
                        .collect(Collectors.toMap(SecondUserCredit::getUserId, c -> c));
            }
            
            // 组装返回结果
            List<SellerEvaluationVo> evaluationList = new java.util.ArrayList<>();
            for (SecondTradeRecord trade : tradeRecords) {
                SellerEvaluationVo vo = new SellerEvaluationVo();
                
                // 交易基本信息
                vo.setId(trade.getId());
                vo.setTradeNo(trade.getTradeNo());
                vo.setGoodsId(trade.getGoodsId());
                vo.setTransactionAmount(trade.getTransactionAmount());
                vo.setBuyerId(trade.getBuyerId());
                vo.setBuyerEvaluate(trade.getBuyerEvaluate());
                // 卖家交易完成时间（评价时间，评分时间）
                vo.setSellerCompleteTime(trade.getSellerCompleteTime());
                // 买家交易完成时间（评价时间，评分时间）
                vo.setBuyerCompleteTime(trade.getBuyerCompleteTime());
                vo.setBuyerRating(trade.getBuyerRating());
                vo.setTransactionTime(trade.getTransactionTime());
                vo.setTradeStatus(trade.getTradeStatus());
                vo.setCreatedTime(trade.getCreatedTime());
                
                // 商品信息
                SecondGoodsRecord goodsRecord = goodsRecordMap.get(trade.getGoodsRecordId());
                if (goodsRecord != null) {
                    vo.setGoodsTitle(goodsRecord.getTitle());
                    vo.setGoodsHomeImage(goodsRecord.getHomeImage());
                    vo.setGoodsPrice(goodsRecord.getPrice());
                }
                
                // 买家用户信息
                LifeUser buyer = buyerMap.get(trade.getBuyerId());
                if (buyer != null) {
                    vo.setBuyerName(buyer.getUserName());
                    vo.setBuyerImage(buyer.getUserImage());
                    vo.setBuyerPhone(buyer.getUserPhone());
                    vo.setBuyerRealName(buyer.getRealName());
                    vo.setBuyerSex(buyer.getUserSex());
                    vo.setBuyerJianjie(buyer.getJianjie());
                }
                
                // 买家信用积分和风控评分等级
                SecondUserCredit buyerCredit = creditMap.get(trade.getBuyerId());
                if (buyerCredit != null) {
                    vo.setBuyerCreditScore(buyerCredit.getUserPoints());
                } else {
                    vo.setBuyerCreditScore(0);
                }
                vo.setBuyerCreditLevel(calculateCreditLevel(trade.getBuyerId()));
                
                // 卖家信息
                vo.setSellerId(sellerId);
                if (seller != null) {
                    vo.setSellerName(seller.getUserName());
                    vo.setSellerImage(seller.getUserImage());
                }
                
                // 卖家信用积分和风控评分等级
                SecondUserCredit sellerCredit = creditMap.get(sellerId);
                if (sellerCredit != null) {
                    vo.setSellerCreditScore(sellerCredit.getUserPoints());
                } else {
                    vo.setSellerCreditScore(0);
                }
                vo.setSellerCreditLevel(calculateCreditLevel(sellerId));
                
                evaluationList.add(vo);
            }
            
            // 构建分页返回对象
            Page<SellerEvaluationVo> resultPage = new Page<>(pageNum, pageSize);
            resultPage.setRecords(evaluationList);
            resultPage.setTotal(tradePage.getTotal());
            resultPage.setPages(tradePage.getPages());
            
            log.info("SecondTradeRecordServiceImpl.getSellerEvaluationList(): 查询到{}条评价记录，共{}页", 
                    evaluationList.size(), resultPage.getPages());
            return resultPage;
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.getSellerEvaluationList(): Error Msg={}", e.getMessage(), e);
            throw new Exception("获取卖家评价列表失败: " + e.getMessage());
        }
    }

    @Override
    public void locationShareAdd(Integer otherUserId) throws Exception {
        try {
            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            String key = getKey(userId, otherUserId);

            if (baseRedisService.hasKey(key)) {
                JSONArray array = JSONArray.parseArray(baseRedisService.getString(key));
                if (!array.contains(userId)) array.add(userId);
                baseRedisService.setString(key, array.toJSONString());
            } else {
                JSONArray array = new JSONArray();
                array.add(userId);
                baseRedisService.setString(key, array.toJSONString());
            }
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.locationShareAdd(): Error Msg={}", e.getMessage(), e);
            throw new Exception("添加位置共享失败: " + e.getMessage());
        }
    }

    @Override
    public void locationShareDel(Integer otherUserId) throws Exception {
        try {
            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            String key = getKey(userId, otherUserId);

            // 存在key，则删除
            if (baseRedisService.hasKey(key)) {
                JSONArray array = JSONArray.parseArray(baseRedisService.getString(key));
                array.remove(userId);
                if (array.isEmpty()) {
                    baseRedisService.delete(key);
                    LifeUser user = lifeUserMapper.selectById(userId);
                    LifeUser otherUser = lifeUserMapper.selectById(otherUserId);
                    LambdaQueryWrapper<LifeMessage> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(LifeMessage::getType, 10);
                    wrapper.isNull(LifeMessage::getContent);
                    lifeMessageUtil.applyConversationQuery(wrapper,
                            "user_" + user.getUserPhone(), "user_" + otherUser.getUserPhone());
                    List<Integer> messageIds = lifeMessageMapper.selectList(wrapper).stream().map(LifeMessage::getId).collect(Collectors.toList());

                    if (CollectionUtils.isNotEmpty(messageIds)) {
                        // 修改消息状态
                        JSONObject messageJson = new JSONObject();
                        messageJson.put("cardType", 2);
                        LambdaUpdateWrapper<LifeMessage> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.in(LifeMessage::getId, messageIds);
                        updateWrapper.set(LifeMessage::getContent, messageJson.toJSONString());
                        lifeMessageMapper.update(null, updateWrapper);

                        // 发起交易人信息
                        String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");

                        // 获取交易对方信息
                        LifeUser lifeUser = lifeUserMapper.selectById(otherUserId);
                        String receiverId = "user_" + lifeUser.getUserPhone();

                        // 给买家与卖家发送交易消息
                        WebSocketVo webSocketVo = new WebSocketVo();
                        webSocketVo.setSenderId(phoneId);
                        webSocketVo.setReceiverId(receiverId);
                        webSocketVo.setCategory("message");
                        webSocketVo.setType("10");
                        webSocketVo.setIsRead(0);
                        webSocketVo.setText(messageJson.toJSONString());
                        webSocketVo.setMessageIdList(messageIds);

                        alienStoreFeign.sendMsgToClientByPhoneId(phoneId, JSONObject.from(webSocketVo).toJSONString());
                        alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());
                    }
                } else {
                    baseRedisService.setString(key, array.toJSONString());
                }
            }
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.locationShareDel(): Error Msg={}", e.getMessage(), e);
            throw new Exception("删除位置共享失败: " + e.getMessage());
        }
    }

    @Override
    public boolean locationShareHas(Integer otherUserId) throws Exception {
        try {
            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
            String key = getKey(userId, otherUserId);

            // 是否存在定位信息
            if (baseRedisService.hasKey(key) && !JSONArray.parseArray(baseRedisService.getString(key)).isEmpty()) {
                return true;
            } else {
                baseRedisService.delete(key);
            }

        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.locationShareHas(): Error Msg={}", e.getMessage(), e);
            throw new Exception("获取位置共享状态失败: " + e.getMessage());
        }
        return false;
    }

    @Override
    public boolean logicDeleteByBuyerAndTradeId(Integer userId, Integer tradeId) {
        if (userId == null || tradeId == null) {
            return false;
        }
        LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SecondTradeRecord::getBuyerId, userId);
        wrapper.eq(SecondTradeRecord::getId, tradeId);
        return remove(wrapper);
    }

    private String getKey(Integer userId, Integer otherUserId) {
        // 组合userId和otherUserId作为Redis的key
        // 使用排序方式确保key的一致性（较小的ID在前）
        String key;
        if (userId.compareTo(otherUserId) < 0) {
            key = "second_location_share:" + userId + ":" + otherUserId;
        } else {
            key = "second_location_share:" + otherUserId + ":" + userId;
        }
        return key;
    }

    /**
     * 计算用户风控评分等级
     * 根据用户违规次数计算等级：O(无记录) < A(1-2次) < B(3-5次) < C(6-9次) < D(10-14次) < E(≥15次)
     *
     * @param userId 用户ID
     * @return 风控评分等级
     */
    private String calculateCreditLevel(Integer userId) {
        try {
            if (userId == null) {
                return "O";
            }
            
            // 查询用户违规记录数量
            LambdaQueryWrapper<SecondRiskControlRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SecondRiskControlRecord::getUserId, userId)
                    .eq(SecondRiskControlRecord::getDeleteFlag, 0);
            
            Integer count = secondRiskControlRecordMapper.selectCount(wrapper);
            int violationCount = count != null ? count : 0;
            
            // 根据违规次数确定等级
            if (violationCount == 0) {
                return "O";  // 无记录
            } else if (violationCount >= 15) {
                return "E";  // 最差
            } else if (violationCount >= 10) {
                return "D";
            } else if (violationCount >= 6) {
                return "C";
            } else if (violationCount >= 3) {
                return "B";
            } else {
                return "A";  // 1-2次违规
            }
        } catch (Exception e) {
            log.error("SecondTradeRecordServiceImpl.calculateCreditLevel(): Error Msg={}", e.getMessage(), e);
            return "O";  // 异常时返回默认等级
        }
    }
}
