package shop.alien.store.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.stereotype.Service;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.LifeDiscountCouponStoreFriendDto;
import shop.alien.entity.store.vo.*;
import shop.alien.entity.storePlatform.StoreOperationalActivity;
import shop.alien.mapper.*;
import shop.alien.mapper.storePlantform.StoreOperationalActivityMapper;
import shop.alien.store.config.WebSocketProcess;
import shop.alien.store.service.LifeDiscountCouponStoreFriendService;
import shop.alien.util.common.constant.DiscountCouponEnum;
import shop.alien.util.coupon.DiscountCouponExpirationUtil;
import shop.alien.util.coupon.LifeDiscountCouponStock;
import shop.alien.util.type.LifeFansIdentityQuery;
import shop.alien.util.type.LifeNoticeUtil;
import shop.alien.util.type.TypeUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 好友赠券领域：配置可赠券、执行赠送（扣库存 + 写 ldcsf）、消费后发券、赠券历史查询等。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LifeDiscountCouponStoreFriendServiceImpl extends ServiceImpl<LifeDiscountCouponStoreFriendMapper, LifeDiscountCouponStoreFriend> implements LifeDiscountCouponStoreFriendService {

    /** {@link #getReceivedSendFriendCouponList} 的 queryType：我收到的 */
    private static final int GIFT_HISTORY_QUERY_RECEIVED = 1;
    /** {@link #getReceivedSendFriendCouponList} 的 queryType：我送出的 */
    private static final int GIFT_HISTORY_QUERY_SENT = 2;

    final String STORE_PREFIX = "store_";

    /** 单次好评发券的张数上限，防止运营误填特大数字 */
    private static final int GOOD_RATING_ISSUE_COPIES_HARD_CAP = 50;

    private final StoreUserMapper storeUserMapper;

    private final LifeFansMapper lifeFansMapper;
    private final TypeUtil typeUtil;

    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;

    private final LifeDiscountCouponStoreFriendMapper lifeDiscountCouponStoreFriendMapper;

    private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;

    private final LifeUserOrderMapper lifeUserOrderMapper;

    private final LifeDiscountCouponStoreFriendSendRecordMapper lifeDiscountCouponStoreFriendSendRecordMapper;

    private final StoreInfoMapper storeInfoMapper;

    private final LifeUserMapper lifeUserMapper;

    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeNoticeUtil lifeNoticeUtil;

    private final LifeDiscountCouponFriendRuleMapper lifeDiscountCouponFriendRuleMapper;

    private final LifeDiscountCouponFriendRuleDetailMapper lifeDiscountCouponFriendRuleDetailMapper;

    private final WebSocketProcess webSocketProcess;

    private final StoreOperationalActivityMapper storeOperationalActivityMapper;

    private final CommonRatingMapper commonRatingMapper;

    private final UserReservationOrderMapper userReservationOrderMapper;

    @Override
    public List<LifeDiscountCouponStoreFriendVo> getFriendCouponList(UserLoginInfo userLoginInfo, String friendUserId) {
        List<LifeDiscountCouponStoreFriendVo> result = new ArrayList<>();
        //登录人是店铺用户这个获取到的是店铺用户id
        String phoneNumber = userLoginInfo.getUserPhone();
        //查询该店铺登录人 fans 表互相关注的列表
        String fansUserPhone = STORE_PREFIX + phoneNumber;
        //查看自己关注的店铺
        LifeFansIdentityQuery.Scope fansScope = LifeFansIdentityQuery.resolve(fansUserPhone, typeUtil);
        LambdaQueryWrapper<LifeFans> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LifeFans::getDeleteFlag, 0);
        LifeFansIdentityQuery.applyFansSide(queryWrapper, fansScope);
        queryWrapper.eq(LifeFans::getFollowedUserType, 2);
        List<LifeFans> lifeFans = lifeFansMapper.selectList(queryWrapper);
        //循环本人关注列表查看也关注我的列表
        for (LifeFans lifeFan : lifeFans) {
            //关注人id
            String followedId = lifeFan.getFollowedId();
            LifeFansIdentityQuery.Scope followedScope = LifeFansIdentityQuery.resolve(followedId, typeUtil);
            LambdaQueryWrapper<LifeFans> mutualWrapper = new LambdaQueryWrapper<>();
            LifeFansIdentityQuery.applyPairWithDeleteFlag(mutualWrapper, followedScope, fansScope);
            LifeFans alsoFansMe = lifeFansMapper.selectOne(mutualWrapper);
            //如果有值说明我俩互为朋友
            if (alsoFansMe != null) {
                LifeDiscountCouponStoreFriendVo addLifeDiscountCouponStoreFriendVo = new LifeDiscountCouponStoreFriendVo();
                //拿手机号查询一下
                StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getPhone, followedId.substring(STORE_PREFIX.length())));
                //如果不为空，或不相等
                if (StringUtils.isNotEmpty(friendUserId) && !friendUserId.equals(storeUser.getId().toString())) {
                    continue;
                }
                addLifeDiscountCouponStoreFriendVo.setFriendStoreUserName(storeUser.getName());
                addLifeDiscountCouponStoreFriendVo.setFriendStoreUserId(storeUser.getId());
                //查询该店铺的券
                LambdaQueryWrapper<LifeDiscountCoupon> couponQueryWrapper = new LambdaQueryWrapper<>();

                // 获取当前日期
                LocalDate currentDate = LocalDate.now();

                // 截取前缀之后的部分（可用券，开放领取，并且还没结束的券）
                couponQueryWrapper
                        .eq(LifeDiscountCoupon::getStoreId, storeUser.getStoreId())
                        .eq(LifeDiscountCoupon::getGetStatus, DiscountCouponEnum.CAN_GET)
                        .ge(LifeDiscountCoupon::getEndDate, currentDate)
                ;
                List<LifeDiscountCoupon> lifeDiscountCoupons = lifeDiscountCouponMapper.selectList(couponQueryWrapper);
                List<LifeDiscountCouponVo> lifeDiscountCouponVoList = new ArrayList<>();
                for (LifeDiscountCoupon lifeDiscountCoupon : lifeDiscountCoupons) {
                    LifeDiscountCouponVo lifeDiscountCouponVo = new LifeDiscountCouponVo();
                    BeanUtils.copyProperties(lifeDiscountCoupon, lifeDiscountCouponVo);
                    lifeDiscountCouponVo.setCouponId(lifeDiscountCoupon.getId());
                    lifeDiscountCouponVoList.add(lifeDiscountCouponVo);
                }
                addLifeDiscountCouponStoreFriendVo.setFriendStoreCouponList(lifeDiscountCouponVoList);
                result.add(addLifeDiscountCouponStoreFriendVo);
            }
        }

        return result;
    }

    /**
     * 向好友店铺赠送优惠券：按券列表逐笔调用 {@link #handleDiscountFriendCoupon}（库存 + ldcsf）。
     */
    @Override
    public boolean setFriendCoupon(UserLoginInfo userLoginInfo, LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto) {
        try {
            List<LifeDiscountCouponStoreFriendDto> coupons = lifeDiscountCouponStoreFriendDto.getCouponIds();
            if (CollectionUtils.isEmpty(coupons)) {
                return true;
            }
            for (LifeDiscountCouponStoreFriendDto couponDto : coupons) {
                if (couponDto.getCouponId() != null
                        && !handleDiscountFriendCoupon(userLoginInfo, lifeDiscountCouponStoreFriendDto, couponDto)) {
                    return false;
                }
            }
            return true;
        } catch (BeansException e) {
            e.printStackTrace();
            return false;
        }
    }

    private static Integer parseStoreIdInt(String raw) {
        if (raw == null) {
            return null;
        }
        String t = raw.trim();
        if (t.isEmpty()) {
            return null;
        }
        try {
            return Integer.parseInt(t);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    /**
     * 同券同赠送人同接收店铺：新旧列任一命中即合并 single_qty（仅 life_discount_coupon 优惠券模板）。
     */
    private LambdaQueryWrapper<LifeDiscountCouponStoreFriend> duplicateGiftRowWrapper(
            Integer couponId, Integer receiverStoreId, int senderUserId) {
        LambdaQueryWrapper<LifeDiscountCouponStoreFriend> w = new LambdaQueryWrapper<>();
        if (couponId == null) {
            w.eq(LifeDiscountCouponStoreFriend::getId, -1);
            return w;
        }
        w.eq(LifeDiscountCouponStoreFriend::getCouponId, couponId)
                .isNull(LifeDiscountCouponStoreFriend::getVoucherId);
        w.apply("( (receiver_store_id = {0} AND sender_user_id = {1}) OR (receiver_store_id IS NULL AND store_user_id = {0} AND friend_store_user_id = {1}) )",
                receiverStoreId, senderUserId);
        return w;
    }

    /**
     * 赠送方 / 接收方新旧列对齐：receiver/store_user_id、sender/friend_store_user_id 同源，便于历史脚本与 Mapper 仍可读。
     */
    private void applyGiftParties(LifeDiscountCouponStoreFriend row, int senderUserId, Integer receiverStoreId, Integer receiverUserId) {
        StoreUser sender = storeUserMapper.selectById(senderUserId);
        Integer senderStoreId = sender != null ? sender.getStoreId() : null;
        row.setSenderUserId(senderUserId);
        row.setSenderStoreId(senderStoreId);
        row.setReceiverStoreId(receiverStoreId);
        row.setReceiverUserId(receiverUserId);
        row.setFriendStoreUserId(senderUserId);
        row.setStoreUserId(receiverStoreId);
    }

    /**
     * 写入/更新 {@link LifeDiscountCouponStoreFriend} 时，有效期相关字段仅以「按 couponId 查到的」{@link LifeDiscountCoupon} 为准（请求体 DTO 对应属性已 JsonIgnore）。
     */
    private static void applyGiftValiditySnapshotFromTemplate(LifeDiscountCouponStoreFriend row, LifeDiscountCoupon template) {
        row.setExpirationDate(template.getExpirationDate());
        row.setLongTermValid(template.getLongTermValid());
        row.setStartDate(template.getStartDate());
        row.setEndDate(template.getEndDate());
    }

    /**
     * 接收方商户用户：请求体显式传入优先；未传时按接收方店铺取一条未删除的商户账号（与赠券通知选取逻辑一致，便于四字段落库）。
     */
    private Integer resolveReceiverUserId(Integer receiverStoreId, Integer explicitReceiverUserId) {
        if (explicitReceiverUserId != null) {
            return explicitReceiverUserId;
        }
        if (receiverStoreId == null) {
            return null;
        }
        List<StoreUser> list = storeUserMapper.selectList(new LambdaQueryWrapper<StoreUser>()
                .eq(StoreUser::getStoreId, receiverStoreId)
                .eq(StoreUser::getDeleteFlag, 0)
                .orderByAsc(StoreUser::getId)
                .last("LIMIT 1"));
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0).getId();
    }

    /**
     * 接收方维度筛选：优先 {@code receiver_store_id}，兼容旧列 {@code store_user_id}（均为 store_info.id）。
     */
    private void applyLdcsfReceiverStoreFilter(QueryWrapper<?> q, int receiverStoreInfoId) {
        q.and(w -> w.eq("ldcsf.receiver_store_id", receiverStoreInfoId)
                .or(sub -> sub.isNull("ldcsf.receiver_store_id").eq("ldcsf.store_user_id", receiverStoreInfoId)));
    }

    /**
     * 赠送方维度筛选：优先 {@code sender_user_id}，兼容旧列 {@code friend_store_user_id}（均为 store_user.id）。
     */
    private void applyLdcsfSenderMerchantFilter(QueryWrapper<?> q, int senderStoreUserId) {
        q.and(w -> w.eq("ldcsf.sender_user_id", senderStoreUserId)
                .or(sub -> sub.isNull("ldcsf.sender_user_id").eq("ldcsf.friend_store_user_id", senderStoreUserId)));
    }

    /** 处理优惠券（life_discount_coupon）发放好友 */
    private boolean handleDiscountFriendCoupon(UserLoginInfo userLoginInfo, LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto, LifeDiscountCouponStoreFriendDto couponDto) {
        LifeDiscountCoupon lifeDiscountCoupon = lifeDiscountCouponMapper.selectById(couponDto.getCouponId());
        Integer receiverStoreId = lifeDiscountCouponStoreFriendDto.getFriendStoreUserId();
        if (lifeDiscountCoupon == null || receiverStoreId == null) {
            return false;
        }
        Integer receiverUserId = resolveReceiverUserId(receiverStoreId, lifeDiscountCouponStoreFriendDto.getReceiverUserId());
        int sendQty = couponDto.getSingleQty() != null ? couponDto.getSingleQty() : 0;
        if (!LifeDiscountCouponStock.isUnlimitedQty(lifeDiscountCoupon.getUnlimitedQty())) {
            if (lifeDiscountCoupon.getSingleQty() == null
                    || (lifeDiscountCoupon.getSingleQty() - sendQty) < 0) {
                return false;
            }
        }
        Integer tplStoreId = parseStoreIdInt(lifeDiscountCoupon.getStoreId());
        if (tplStoreId == null) {
            return false;
        }
        Integer tplMerchantCount = storeUserMapper.selectCount(new LambdaQueryWrapper<StoreUser>()
                .eq(StoreUser::getStoreId, tplStoreId).eq(StoreUser::getDeleteFlag, 0));
        if (tplMerchantCount == null || tplMerchantCount == 0) {
            return false;
        }

        LifeDiscountCouponStoreFriend lifeDiscountCouponStoreFriend = lifeDiscountCouponStoreFriendMapper.selectOne(
                duplicateGiftRowWrapper(couponDto.getCouponId(), receiverStoreId, userLoginInfo.getUserId())
        );

        if (lifeDiscountCouponStoreFriend == null) {
            lifeDiscountCouponStoreFriend = new LifeDiscountCouponStoreFriend();
            lifeDiscountCouponStoreFriend.setCouponId(couponDto.getCouponId());
            lifeDiscountCouponStoreFriend.setVoucherId(null);
            applyGiftValiditySnapshotFromTemplate(lifeDiscountCouponStoreFriend, lifeDiscountCoupon);
            lifeDiscountCouponStoreFriend.setSingleQty(couponDto.getSingleQty());
            lifeDiscountCouponStoreFriend.setReleaseType(1);
            applyGiftParties(lifeDiscountCouponStoreFriend, userLoginInfo.getUserId(), receiverStoreId, receiverUserId);
            lifeDiscountCouponStoreFriendMapper.insert(lifeDiscountCouponStoreFriend);
        } else {
            applyGiftParties(lifeDiscountCouponStoreFriend, userLoginInfo.getUserId(), receiverStoreId, receiverUserId);
            applyGiftValiditySnapshotFromTemplate(lifeDiscountCouponStoreFriend, lifeDiscountCoupon);
            lifeDiscountCouponStoreFriend.setSingleQty(lifeDiscountCouponStoreFriend.getSingleQty() + couponDto.getSingleQty());
            lifeDiscountCouponStoreFriendMapper.updateById(lifeDiscountCouponStoreFriend);
        }
        if (!LifeDiscountCouponStock.isUnlimitedQty(lifeDiscountCoupon.getUnlimitedQty())
                && lifeDiscountCoupon.getSingleQty() != null) {
            lifeDiscountCoupon.setSingleQty(lifeDiscountCoupon.getSingleQty() - sendQty);
        }
        lifeDiscountCouponMapper.updateById(lifeDiscountCoupon);
        sendFriendCouponNotice(lifeDiscountCouponStoreFriendDto.getFriendStoreUserId(), userLoginInfo, couponDto.getSingleQty());
        return true;
    }

    /** 发送赠券通知 */
    private void sendFriendCouponNotice(Integer friendStoreUserId, UserLoginInfo userLoginInfo, int qty) {
        if (friendStoreUserId == null) {
            return;
        }
        LambdaQueryWrapper<StoreUser> storeUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeUserLambdaQueryWrapper.eq(StoreUser::getStoreId, friendStoreUserId);
        List<StoreUser> storeUserList = storeUserMapper.selectList(storeUserLambdaQueryWrapper);
        if (CollectionUtils.isEmpty(storeUserList)) {
            return;
        }
        StoreUser friendStoreUser = storeUserList.get(0);
        String friendPhone = friendStoreUser.getPhone();
        if (friendPhone == null || friendPhone.trim().isEmpty()) {
            return;
        }
        String storeName = userLoginInfo.getUserName();
        StoreUser currentStoreUser = storeUserMapper.selectById(userLoginInfo.getUserId());
        if (currentStoreUser != null && currentStoreUser.getStoreId() != null) {
            StoreInfo currentStoreInfo = storeInfoMapper.selectById(currentStoreUser.getStoreId());
            if (currentStoreInfo != null && currentStoreInfo.getStoreName() != null) {
                storeName = currentStoreInfo.getStoreName();
            }
        }
        LifeNotice lifeMessage = new LifeNotice();
        String text = "您的好友" + storeName + "送了您" + qty + "张优惠券";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", text);
        lifeMessage.setReceiverId("store_" + friendPhone);
        lifeMessage.setTitle("赠券通知");
        lifeMessage.setContext(jsonObject.toJSONString());
        lifeMessage.setNoticeType(1);
        lifeMessage.setIsRead(0);
        lifeMessage.setDeleteFlag(0);
        lifeMessage.setSenderId("system");
        lifeNoticeUtil.fillUserTypeAndRefId(lifeMessage);
        lifeNoticeMapper.insert(lifeMessage);
    }

    /**
     * 为当前用户发放店铺为好友设定的可用优惠券。
     *
     * @param lifeDiscountCouponStoreFriendDto 包含店铺ID等信息的DTO对象
     * @return 成功发放的优惠券信息列表
     */
    @Override
    public List<LifeDiscountCouponStoreFriendVo> issueFriendCoupon(LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto) {

        // 用于存储最终成功发放的优惠券信息的列表
        List<LifeDiscountCouponStoreFriendVo> result = new ArrayList<>();

        //判断该订单是否已经发放过好友店铺优惠券
        LifeUserOrder lifeUserOrder = lifeUserOrderMapper.selectById(lifeDiscountCouponStoreFriendDto.getOrderId());
        if (lifeUserOrder.getSendDiscountCouponFlag() == 1) {
            throw new RuntimeException("已发放优惠券");
        }

        //送券规则
        List<Integer> couponList = new ArrayList<>();
        LambdaQueryWrapper<LifeDiscountCouponFriendRule> ruleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        ruleLambdaQueryWrapper.eq(LifeDiscountCouponFriendRule::getStoreId, lifeUserOrder.getStoreId())
                .eq(LifeDiscountCouponFriendRule::getDeleteFlag, 0);
        List<LifeDiscountCouponFriendRule> lifeDiscountCouponFriendRules = lifeDiscountCouponFriendRuleMapper.selectList(ruleLambdaQueryWrapper);
        lifeDiscountCouponFriendRules = lifeDiscountCouponFriendRules.stream().filter(i -> i.getMoneyLow().compareTo(new BigDecimal(lifeUserOrder.getFinalPrice())) <= 0 && i.getMoneyHigh().compareTo(new BigDecimal(lifeUserOrder.getFinalPrice())) >= 0).collect(Collectors.toList());
        if (ObjectUtils.isNotEmpty(lifeDiscountCouponFriendRules)) {
            LambdaQueryWrapper<LifeDiscountCouponFriendRuleDetail> detailLambdaQueryWrapper = new LambdaQueryWrapper<>();
            detailLambdaQueryWrapper.in(LifeDiscountCouponFriendRuleDetail::getRuleId, lifeDiscountCouponFriendRules.stream().map(LifeDiscountCouponFriendRule::getId).collect(Collectors.toList()));
            List<LifeDiscountCouponFriendRuleDetail> lifeDiscountCouponFriendRuleDetails = lifeDiscountCouponFriendRuleDetailMapper.selectList(detailLambdaQueryWrapper);
            couponList = lifeDiscountCouponFriendRuleDetails.stream().map(LifeDiscountCouponFriendRuleDetail::getCouponId).collect(Collectors.toList());
        }


        lifeUserOrder.setSendDiscountCouponFlag(1);
        lifeUserOrderMapper.updateById(lifeUserOrder);

        //有符合规则的优惠券
        if (ObjectUtils.isNotEmpty(couponList) && !couponList.isEmpty()) {
            // 获取当前消费用户的ID
            int userId = Integer.parseInt(lifeUserOrder.getUserId());
            LifeUser lifeUser = lifeUserMapper.selectById(userId);
            // 从传入的DTO对象中获取店铺ID
            StoreUser storeUser =
                    storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, lifeUserOrder.getStoreId()));
            Integer storeUserId = storeUser.getId();
            Integer storeId = storeUser.getStoreId();
            StoreInfo storeInfo = storeInfoMapper.selectById(storeUser.getStoreId());

            // 根据店铺ID从数据库中查询该店铺为好友设定的所有优惠券信息
            List<LifeDiscountCouponStoreFriend> lifeDiscountCouponStoreFriends = lifeDiscountCouponStoreFriendMapper.selectList(
                    new LambdaQueryWrapper<LifeDiscountCouponStoreFriend>()
                            .and(w -> w.eq(LifeDiscountCouponStoreFriend::getReceiverStoreId, storeId)
                                    .or(sub -> sub.isNull(LifeDiscountCouponStoreFriend::getReceiverStoreId)
                                            .eq(LifeDiscountCouponStoreFriend::getStoreUserId, storeId)))
                            .eq(LifeDiscountCouponStoreFriend::getReleaseType, 1)
                            .in(LifeDiscountCouponStoreFriend::getCouponId, couponList));

            // 获取当前日期，用于后续判断优惠券是否在有效期内
            LocalDate currentDate = LocalDate.now();
            if (!lifeDiscountCouponStoreFriends.isEmpty()) {
                // 遍历该店铺为好友设定的所有优惠券信息
                for (LifeDiscountCouponStoreFriend coupon : lifeDiscountCouponStoreFriends) {
                    // 创建一个Lambda查询包装器，用于构建查询优惠券的条件
                    LambdaQueryWrapper<LifeDiscountCoupon> queryWrapper = new LambdaQueryWrapper<>();
                    // 设置查询条件：优惠券的领取状态为可领取
                    queryWrapper.eq(LifeDiscountCoupon::getGetStatus, DiscountCouponEnum.CAN_GET.getValue());
                    // 设置查询条件：优惠券的ID等于当前遍历到的优惠券ID
                    queryWrapper.eq(LifeDiscountCoupon::getId, coupon.getCouponId());
                    // 设置查询条件：优惠券的结束日期大于等于当前日期，即优惠券在有效期内
                    queryWrapper.ge(LifeDiscountCoupon::getValidDate, currentDate);
                    // 设置查询条件：优惠券还有库存
                    queryWrapper.and(w -> w.eq(LifeDiscountCoupon::getUnlimitedQty, 1)
                            .or()
                            .gt(LifeDiscountCoupon::getSingleQty, 0));

                    // 根据上述查询条件从数据库中查询符合条件的优惠券信息
                    LifeDiscountCoupon lifeDiscountCoupon = lifeDiscountCouponMapper.selectOne(queryWrapper);

                    // 如果查询到符合条件的优惠券，说明该优惠券可领
                    if (lifeDiscountCoupon != null) {
                        // 设定本次领取优惠券的数量，这里固定为1张
                        Integer receiveQuantity = 1;

                        // 循环领取优惠券，根据设定的领取数量进行多次领取操作
                        for (int i = 0; i < receiveQuantity; i++) {
                            // 创建一个新的用户优惠券记录对象
                            LifeDiscountCouponUser lifeDiscountCouponUser = new LifeDiscountCouponUser();
                            // 设置该优惠券记录的优惠券ID
                            lifeDiscountCouponUser.setCouponId(coupon.getCouponId());
                            // 设置该优惠券记录的用户ID为当前用户ID
                            lifeDiscountCouponUser.setUserId(userId);
                            // 设置该优惠券的领取时间为当前时间
                            lifeDiscountCouponUser.setReceiveTime(new Date());
                            lifeDiscountCouponUser.setExpirationTime(DiscountCouponExpirationUtil.resolveLifeDiscountCouponExpiration(
                                    lifeDiscountCouponUser.getReceiveTime(),
                                    lifeDiscountCoupon.getLongTermValid(),
                                    lifeDiscountCoupon.getSpecifiedDay(),
                                    lifeDiscountCoupon.getExpirationDate(),
                                    lifeDiscountCoupon.getValidDate(),
                                    lifeDiscountCoupon.getEndDate(),
                                    ZoneId.systemDefault()));
                            // 设置该优惠券的状态为待使用
                            lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
                            lifeDiscountCouponUser.setIssueSource(4); // 4-好友赠送
                            // 将该用户优惠券记录插入到数据库中
                            lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
                        }

                        // 削减该优惠券的库存，根据领取数量减少库存
                        coupon.setSingleQty(coupon.getSingleQty() - receiveQuantity);
                        // 更新数据库中该优惠券的库存信息
                        lifeDiscountCouponStoreFriendMapper.updateById(coupon);

                        // 创建一个用于存储优惠券信息的VO对象
                        LifeDiscountCouponStoreFriendVo lifeDiscountCouponStoreFriendVo = new LifeDiscountCouponStoreFriendVo();
                        // 将优惠券信息复制到VO对象中
                        BeanUtils.copyProperties(coupon, lifeDiscountCouponStoreFriendVo);
                        // 将该VO对象添加到最终结果列表中
                        result.add(lifeDiscountCouponStoreFriendVo);
                    }
                }

                //存储发放日志
                LifeDiscountCouponStoreFriendSendRecord lifeDiscountCouponStoreFriendSendRecord = new LifeDiscountCouponStoreFriendSendRecord();
                //存入门店id
                lifeDiscountCouponStoreFriendSendRecord.setStoreId(Integer.parseInt(lifeUserOrder.getStoreId()));
                //存入接收人id
                lifeDiscountCouponStoreFriendSendRecord.setUserId(userId);
                //存入发放人id
                lifeDiscountCouponStoreFriendSendRecord.setStoreUserId(storeUserId);
                //存入订单id
                lifeDiscountCouponStoreFriendSendRecord.setOrderId(Integer.parseInt(lifeUserOrder.getId()));
                //存入优惠券ids
                String[] couponIds = result.stream()
                        .map(LifeDiscountCouponStoreFriendVo::getCouponId)
                        .map(String::valueOf)  // 将 Integer 转换为 String
                        .toArray(String[]::new);

                String join = String.join(",", couponIds);
                lifeDiscountCouponStoreFriendSendRecord.setDiscountCouponIds(join);
                lifeDiscountCouponStoreFriendSendRecordMapper.insert(lifeDiscountCouponStoreFriendSendRecord);

                //发送公告消息
                LifeNotice lifeNotice = new LifeNotice();
                //存入发送人
                lifeNotice.setSenderId("system");
                //存入接收人
                lifeNotice.setReceiverId("user_" + lifeUser.getUserPhone());
                //存入信息
                String text = storeInfo.getStoreName() + "赠送了您他的好友店铺优惠券，快去我的券包查看吧~";
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("message", text);
                lifeNotice.setContext(jsonObject.toJSONString());
                //存入类型
                lifeNotice.setNoticeType(1);
                lifeNotice.setTitle("赠劵通知");
                lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
                lifeNoticeMapper.insert(lifeNotice);

            }
        }




        // 返回成功发放的优惠券信息列表
        return result;
    }

    @Override
    public List<LifeDiscountCouponStoreFriendVo> newIssueFriendCoupon(LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto) {
        // 用于存储最终成功发放的优惠券信息的列表
        List<LifeDiscountCouponStoreFriendVo> result = new ArrayList<>();

        //判断该订单是否已经发放过好友店铺优惠券
//        LifeUserOrder lifeUserOrder = lifeUserOrderMapper.selectById(lifeDiscountCouponStoreFriendDto.getOrderId());
//        if (lifeUserOrder.getSendDiscountCouponFlag() == 1) {
//            throw new RuntimeException("已发放优惠券");
//        }
        UserReservationOrder userReservationOrder = userReservationOrderMapper.selectById(lifeDiscountCouponStoreFriendDto.getOrderId());

//
//        //送券规则
//        List<Integer> couponList = new ArrayList<>();
//        LambdaQueryWrapper<LifeDiscountCouponFriendRule> ruleLambdaQueryWrapper = new LambdaQueryWrapper<>();
//        ruleLambdaQueryWrapper.eq(LifeDiscountCouponFriendRule::getStoreId, userReservationOrder.getStoreId())
//                .eq(LifeDiscountCouponFriendRule::getDeleteFlag, 0);
//        List<LifeDiscountCouponFriendRule> lifeDiscountCouponFriendRules = lifeDiscountCouponFriendRuleMapper.selectList(ruleLambdaQueryWrapper);
//        lifeDiscountCouponFriendRules = lifeDiscountCouponFriendRules.stream().filter(i -> i.getMoneyLow().compareTo(userReservationOrder.getDepositAmount()) <= 0 && i.getMoneyHigh().compareTo(userReservationOrder.getDepositAmount()) >= 0).collect(Collectors.toList());
//        if (ObjectUtils.isNotEmpty(lifeDiscountCouponFriendRules)) {
//            LambdaQueryWrapper<LifeDiscountCouponFriendRuleDetail> detailLambdaQueryWrapper = new LambdaQueryWrapper<>();
//            detailLambdaQueryWrapper.in(LifeDiscountCouponFriendRuleDetail::getRuleId, lifeDiscountCouponFriendRules.stream().map(LifeDiscountCouponFriendRule::getId).collect(Collectors.toList()));
//            List<LifeDiscountCouponFriendRuleDetail> lifeDiscountCouponFriendRuleDetails = lifeDiscountCouponFriendRuleDetailMapper.selectList(detailLambdaQueryWrapper);
//            couponList = lifeDiscountCouponFriendRuleDetails.stream().map(LifeDiscountCouponFriendRuleDetail::getCouponId).collect(Collectors.toList());
//        }


//        lifeUserOrder.setSendDiscountCouponFlag(1);
//        lifeUserOrderMapper.updateById(lifeUserOrder);

        //有符合规则的优惠券
//        if (ObjectUtils.isNotEmpty(couponList) && !couponList.isEmpty()) {
            // 获取当前消费用户的ID
            int userId = Integer.parseInt(userReservationOrder.getUserId().toString());
            LifeUser lifeUser = lifeUserMapper.selectById(userId);
            // 从传入的DTO对象中获取店铺ID
            StoreUser storeUser =
                    storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, userReservationOrder.getStoreId()));
            Integer storeUserId = storeUser.getId();
            Integer storeId = storeUser.getStoreId();
            StoreInfo storeInfo = storeInfoMapper.selectById(storeUser.getStoreId());

            // 根据店铺ID从数据库中查询该店铺为好友设定的所有优惠券信息
            List<LifeDiscountCouponStoreFriend> lifeDiscountCouponStoreFriends = lifeDiscountCouponStoreFriendMapper.selectList(
                    new LambdaQueryWrapper<LifeDiscountCouponStoreFriend>()
                            .and(w -> w.eq(LifeDiscountCouponStoreFriend::getReceiverStoreId, storeId)
                                    .or(sub -> sub.isNull(LifeDiscountCouponStoreFriend::getReceiverStoreId)
                                            .eq(LifeDiscountCouponStoreFriend::getStoreUserId, storeId)))
                            .eq(LifeDiscountCouponStoreFriend::getReleaseType, 1)
                            .gt(LifeDiscountCouponStoreFriend::getSingleQty, 0)
   //                         .in(LifeDiscountCouponStoreFriend::getCouponId, couponList)
            );

            // 获取当前日期，用于后续判断优惠券是否在有效期内
            LocalDate currentDate = LocalDate.now();
            if (!lifeDiscountCouponStoreFriends.isEmpty()) {
                // 遍历该店铺为好友设定的所有优惠券信息
                for (LifeDiscountCouponStoreFriend coupon : lifeDiscountCouponStoreFriends) {
                    // 创建一个Lambda查询包装器，用于构建查询优惠券的条件
                    LambdaQueryWrapper<LifeDiscountCoupon> queryWrapper = new LambdaQueryWrapper<>();
                    // 设置查询条件：优惠券的领取状态为可领取
                    queryWrapper.eq(LifeDiscountCoupon::getGetStatus, DiscountCouponEnum.CAN_GET.getValue());
                    // 设置查询条件：优惠券的ID等于当前遍历到的优惠券ID
                    queryWrapper.eq(LifeDiscountCoupon::getId, coupon.getCouponId());
                    // 设置查询条件：优惠券的结束日期大于等于当前日期，即优惠券在有效期内
//                    queryWrapper.ge(LifeDiscountCoupon::getValidDate, currentDate);
                    // 设置查询条件：优惠券还有库存
                    queryWrapper.and(w -> w.eq(LifeDiscountCoupon::getUnlimitedQty, 1)
                            .or()
                            .gt(LifeDiscountCoupon::getSingleQty, 0));

                    // 根据上述查询条件从数据库中查询符合条件的优惠券信息
                    LifeDiscountCoupon lifeDiscountCoupon = lifeDiscountCouponMapper.selectOne(queryWrapper);

                    // 如果查询到符合条件的优惠券，说明该优惠券可领
                    if (lifeDiscountCoupon != null  ) {
                        // 设定本次领取优惠券的数量，这里固定为1张
                        Integer receiveQuantity = 1;

                        // 循环领取优惠券，根据设定的领取数量进行多次领取操作
                        for (int i = 0; i < receiveQuantity; i++) {
                            // 创建一个新的用户优惠券记录对象
                            LifeDiscountCouponUser lifeDiscountCouponUser = new LifeDiscountCouponUser();
                            // 设置该优惠券记录的优惠券ID
                            lifeDiscountCouponUser.setCouponId(coupon.getCouponId());
                            // 设置该优惠券记录的用户ID为当前用户ID
                            lifeDiscountCouponUser.setUserId(userId);
                            // 设置该优惠券的领取时间为当前时间
                            lifeDiscountCouponUser.setReceiveTime(new Date());
                            // 设置该优惠券的过期时间为优惠券本身的结束日期
                            lifeDiscountCouponUser.setExpirationTime(lifeDiscountCoupon.getValidDate());
                            // 设置该优惠券的状态为待使用
                            lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
                            lifeDiscountCouponUser.setIssueSource(4); // 4-好友赠送
                            // 将该用户优惠券记录插入到数据库中
                            lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
                        }

                        // 削减该优惠券的库存，根据领取数量减少库存
                        coupon.setSingleQty(coupon.getSingleQty() - receiveQuantity);
                        // 更新数据库中该优惠券的库存信息
                        lifeDiscountCouponStoreFriendMapper.updateById(coupon);

                        // 创建一个用于存储优惠券信息的VO对象
                        LifeDiscountCouponStoreFriendVo lifeDiscountCouponStoreFriendVo = new LifeDiscountCouponStoreFriendVo();
                        // 将优惠券信息复制到VO对象中
                        BeanUtils.copyProperties(coupon, lifeDiscountCouponStoreFriendVo);
                        // 将该VO对象添加到最终结果列表中
                        result.add(lifeDiscountCouponStoreFriendVo);
                    }
                }

                //存储发放日志
                LifeDiscountCouponStoreFriendSendRecord lifeDiscountCouponStoreFriendSendRecord = new LifeDiscountCouponStoreFriendSendRecord();
                //存入门店id
                lifeDiscountCouponStoreFriendSendRecord.setStoreId(Integer.parseInt(userReservationOrder.getStoreId().toString()));
                //存入接收人id
                lifeDiscountCouponStoreFriendSendRecord.setUserId(userId);
                //存入发放人id
                lifeDiscountCouponStoreFriendSendRecord.setStoreUserId(storeUserId);
                //存入订单id
                lifeDiscountCouponStoreFriendSendRecord.setOrderId(Integer.parseInt(userReservationOrder.getId().toString()));
                //存入优惠券ids
                String[] couponIds = result.stream()
                        .map(LifeDiscountCouponStoreFriendVo::getCouponId)
                        .map(String::valueOf)  // 将 Integer 转换为 String
                        .toArray(String[]::new);

                String join = String.join(",", couponIds);
                lifeDiscountCouponStoreFriendSendRecord.setDiscountCouponIds(join);
                lifeDiscountCouponStoreFriendSendRecordMapper.insert(lifeDiscountCouponStoreFriendSendRecord);

                //发送公告消息
                LifeNotice lifeNotice = new LifeNotice();
                //存入发送人
                lifeNotice.setSenderId("system");
                //存入接收人
                lifeNotice.setReceiverId("user_" + lifeUser.getUserPhone());
                //存入信息
                String text = storeInfo.getStoreName() + "赠送了您他的好友店铺优惠券，快去我的券包查看吧~";
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("message", text);
                lifeNotice.setContext(jsonObject.toJSONString());
                //存入类型
                lifeNotice.setNoticeType(1);
                lifeNotice.setTitle("赠劵通知");
                lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
                lifeNoticeMapper.insert(lifeNotice);

            }
//        }
            // 返回成功发放的优惠券信息列表
            return result;
    }

    @Override
    public List<LifeDiscountCouponStoreFriendVo> getSendCoupons(LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto) {
        List<LifeDiscountCouponStoreFriendVo> result = new ArrayList<>();
        Integer orderId = lifeDiscountCouponStoreFriendDto.getOrderId();
        //根据订单id获取发放记录
        LifeDiscountCouponStoreFriendSendRecord lifeDiscountCouponStoreFriendSendRecord =
                lifeDiscountCouponStoreFriendSendRecordMapper.selectOne(
                        new LambdaQueryWrapper<LifeDiscountCouponStoreFriendSendRecord>()
                                .eq(LifeDiscountCouponStoreFriendSendRecord::getOrderId, orderId));
        //如果没查出信息，说明没发
        if (lifeDiscountCouponStoreFriendSendRecord != null) {
            //获取发放的优惠券ids
            String discountCouponIds = lifeDiscountCouponStoreFriendSendRecord.getDiscountCouponIds();
            List<String> list = Arrays.asList(discountCouponIds.split(","));
            for (String couponId : list) {
                LifeDiscountCouponStoreFriendVo lifeDiscountCouponStoreFriendVo = new LifeDiscountCouponStoreFriendVo();
                lifeDiscountCouponStoreFriendVo.setCouponId(Integer.parseInt(couponId));
                result.add(lifeDiscountCouponStoreFriendVo);
            }
        }
        return result;
    }

    @Override
    public int releaseAndCancelFriendStoreCoupon(String giveCouponId, String releaseType) {
        LambdaUpdateWrapper<LifeDiscountCouponStoreFriend> updateWrapper = new LambdaUpdateWrapper<>();
        // 设置更新条件，根据优惠券的 ID 进行更新
        updateWrapper.eq(LifeDiscountCouponStoreFriend::getId, giveCouponId)
                // 设置要更新的字段，将优惠券的状态更新为 3
                .set(LifeDiscountCouponStoreFriend::getReleaseType, releaseType);
        return lifeDiscountCouponStoreFriendMapper.update(null, updateWrapper);
    }

    @Override
    public LifeDiscountCouponFriendRuleVo saveFriendCouponRule(LifeDiscountCouponFriendRule lifeDiscountCouponFriendRule) {
        List<LifeDiscountCouponFriendRuleDetail> details = lifeDiscountCouponFriendRule.getDetails();
        if (ObjectUtils.isNotEmpty(details)) {
            for (LifeDiscountCouponFriendRuleDetail detail : details) {
                detail.setVoucherId(null);
            }
        }
        if (ObjectUtils.isNotEmpty(lifeDiscountCouponFriendRule.getId())) {
            lifeDiscountCouponFriendRuleDetailMapper.delete(new LambdaQueryWrapper<LifeDiscountCouponFriendRuleDetail>().eq(LifeDiscountCouponFriendRuleDetail::getRuleId, lifeDiscountCouponFriendRule.getId()));
            if (ObjectUtils.isNotEmpty(details)) {
                for (LifeDiscountCouponFriendRuleDetail detail : details) {
                    detail.setRuleId(lifeDiscountCouponFriendRule.getId());
                    detail.setStoreId(lifeDiscountCouponFriendRule.getStoreId());
                }
                lifeDiscountCouponFriendRuleDetailMapper.insertList(details);
            }
            lifeDiscountCouponFriendRuleMapper.updateById(lifeDiscountCouponFriendRule);
        } else {
            lifeDiscountCouponFriendRuleMapper.insert(lifeDiscountCouponFriendRule);
            if (ObjectUtils.isNotEmpty(details)) {
                details.forEach(detail -> {
                    detail.setRuleId(lifeDiscountCouponFriendRule.getId());
                    detail.setStoreId(lifeDiscountCouponFriendRule.getStoreId());
                });
                lifeDiscountCouponFriendRuleDetailMapper.insertList(details);
            }
        }
        return getRuleById(lifeDiscountCouponFriendRule.getId().toString());
    }

    @Override
    public void delFriendCouponRule(String id) {
        lifeDiscountCouponFriendRuleDetailMapper.delete(new LambdaQueryWrapper<LifeDiscountCouponFriendRuleDetail>().eq(LifeDiscountCouponFriendRuleDetail::getRuleId, id));
        lifeDiscountCouponFriendRuleMapper.deleteById(id);
    }

    /**
     * 获取好友送的优惠券列表
     *
     * @param storeId 当前登录店铺id
     * @param friendStoreUserId 选中好友店铺用户id
     * @return 领取的优惠券列表
     */
    @Override
    public List<LifeDiscountCouponFriendRuleDetailVo> getReceivedFriendCouponList(String storeId, String friendStoreUserId, Integer type, Integer couponType) {
        if (Integer.valueOf(4).equals(type)) {
            return new ArrayList<>();
        }
        QueryWrapper<LifeDiscountCouponFriendRuleDetailVo> queryWrapper = new QueryWrapper<>();
        try {
            applyLdcsfReceiverStoreFilter(queryWrapper, Integer.parseInt(storeId.trim()));
        } catch (NumberFormatException e) {
            log.warn("getReceivedFriendCouponList 非法 storeId={}", storeId);
            return new ArrayList<>();
        }
        queryWrapper.eq("ldcsf.delete_flag", 0);
        queryWrapper.eq("ldcsf.release_type", 1);
        queryWrapper.isNotNull("ldcsf.coupon_id");
        //如果指定了优惠券类型（满减券或折扣券），添加筛选条件
        if (couponType != null) {
            queryWrapper.eq("ldc.coupon_type", couponType);
        }
        if (StringUtils.isEmpty(friendStoreUserId)) {
            queryWrapper.groupBy("COALESCE(ldcsf.sender_user_id, ldcsf.friend_store_user_id)").orderByDesc("couponNum");
        } else {
            appendFriendSenderFilter(queryWrapper, friendStoreUserId);
            queryWrapper.groupBy("ldcsf.coupon_id").orderByDesc("couponNum");
        }
        return lifeDiscountCouponFriendRuleDetailMapper.getReceivedFriendCouponList(queryWrapper);
    }

    @Override
    public List<LifeDiscountCouponFriendRuleVo> getRuleList(String storeId, String acName, String status) {
        // 参数校验
        if (StringUtils.isEmpty(storeId)) {
            log.warn("getRuleList 参数错误：storeId 不能为空");
            return new ArrayList<>();
        }
        
        // 查询规则列表（一个规则可能关联多个优惠券，会返回多条记录）
        List<LifeDiscountCouponFriendRuleVo> ruleList = lifeDiscountCouponFriendRuleDetailMapper.getRuleList(storeId);
        if (ruleList == null) {
            ruleList = new ArrayList<>();
        }
        
        // 计算状态：根据结束日期判断活动是否已结束
        // 状态：0-启用（活动进行中），1-禁用（活动已结束）
        if (ObjectUtils.isNotEmpty(ruleList)) {
            Date now = new Date();
            ruleList.forEach(i -> {
                if (i.getEndDate() != null) {
                    // 如果结束日期在当前时间之后，活动进行中（启用）
                    // 如果结束日期在当前时间之前或等于，活动已结束（禁用）
                    i.setStatus(i.getEndDate().after(now) ? "0" : "1");
                } else {
                    // 如果结束日期为null，视为永久有效，状态为启用
                    i.setStatus("0");
                }
            });
        }
        
        // 按规则ID分组去重：同一个规则ID只保留第一条记录（避免一个规则关联多个优惠券时重复展示）
        Map<Integer, LifeDiscountCouponFriendRuleVo> ruleMap = new LinkedHashMap<>();
        for (LifeDiscountCouponFriendRuleVo rule : ruleList) {
            if (rule.getId() != null && !ruleMap.containsKey(rule.getId())) {
                ruleMap.put(rule.getId(), rule);
            }
        }
        ruleList = new ArrayList<>(ruleMap.values());
        
        // 根据活动名称过滤（模糊查询）
        if (StringUtils.isNotEmpty(acName)) {
            String name = acName.trim();
            ruleList = ruleList.stream()
                    .filter(i -> i.getAcName() != null && i.getAcName().contains(name))
                    .collect(Collectors.toList());
        }
        
        // 根据状态过滤
        if (StringUtils.isNotEmpty(status)) {
            String s = status.trim();
            ruleList = ruleList.stream()
                    .filter(i -> i.getStatus() != null && i.getStatus().equals(s))
                    .collect(Collectors.toList());
        }
        
        return ruleList;
    }

    @Override
    public LifeDiscountCouponFriendRuleVo getRuleById(String id) {
        LifeDiscountCouponFriendRule lifeDiscountCouponFriendRule = lifeDiscountCouponFriendRuleMapper.selectById(id);
        LifeDiscountCouponFriendRuleVo ruleVo = new LifeDiscountCouponFriendRuleVo();
        BeanUtils.copyProperties(lifeDiscountCouponFriendRule, ruleVo);
        if (ObjectUtils.isNotEmpty(lifeDiscountCouponFriendRule)) {
            List<LifeDiscountCouponFriendRuleDetailVo> lifeDiscountCouponFriendRuleDetails = lifeDiscountCouponFriendRuleDetailMapper.getDetailList(lifeDiscountCouponFriendRule.getId().toString());
            ruleVo.setLifeDiscountCouponFriendRuleDetailVos(lifeDiscountCouponFriendRuleDetails);
            
            // 如果规则表中没有 couponType，尝试从关联的优惠券中获取
            if (ruleVo.getCouponType() == null && ObjectUtils.isNotEmpty(lifeDiscountCouponFriendRuleDetails)) {
                for (LifeDiscountCouponFriendRuleDetailVo detail : lifeDiscountCouponFriendRuleDetails) {
                    if (detail.getCouponId() != null && detail.getCouponType() != null) {
                        ruleVo.setCouponType(detail.getCouponType());
                        break;
                    }
                }
            }
        }
        return ruleVo;
    }

    /**
     * 赠券历史（GET /getReceivedSendFriendCouponList）：根据「我收到 / 我送出」筛 ldcsf，再补模板与头像。
     */
    @Override
    public List<LifeDiscountCouponFriendRuleVo> getReceivedSendFriendCouponList(String storeUserId, Integer queryType, String storeName, Integer type, Integer couponType) {
        if (!validateGiftHistoryQueryParams(storeUserId, queryType, couponType)) {
            return new ArrayList<>();
        }

        if (Integer.valueOf(4).equals(type)) {
            return new ArrayList<>();
        }

        boolean isReceivedByMe = (queryType == GIFT_HISTORY_QUERY_RECEIVED);
        return queryCouponList(isReceivedByMe, storeUserId, storeName, couponType);
    }

    private boolean validateGiftHistoryQueryParams(String storeUserId, Integer queryType, Integer couponType) {
        if (StringUtils.isEmpty(storeUserId)) {
            log.error("getReceivedSendFriendCouponList 参数错误：storeUserId 不能为空");
            return false;
        }
        if (queryType == null || (queryType != GIFT_HISTORY_QUERY_RECEIVED && queryType != GIFT_HISTORY_QUERY_SENT)) {
            log.error("getReceivedSendFriendCouponList 参数错误：queryType 必须为 {} 或 {}，当前值={}", GIFT_HISTORY_QUERY_RECEIVED, GIFT_HISTORY_QUERY_SENT, queryType);
            return false;
        }
        if (couponType != null && couponType != 1 && couponType != 2) {
            log.error("getReceivedSendFriendCouponList 参数错误：couponType 必须为 1（满减券）或 2（折扣券），当前值={}", couponType);
            return false;
        }
        return true;
    }

    /**
     * 仅优惠券模板（coupon_id）：拼条件 → 查列表 → 含逻辑删模板补全 → 对方头像 → 按 ldcsf.created_time 倒序（新的在前）。
     */
    private List<LifeDiscountCouponFriendRuleVo> queryCouponList(boolean isReceivedByMe, String storeUserId, String storeName, Integer couponType) {
        QueryWrapper<LifeDiscountCouponFriendRuleVo> couponQuery = buildBaseQueryWrapper(isReceivedByMe, storeUserId, storeName);
        couponQuery.isNotNull("ldcsf.coupon_id");
        // couponType：须保留「模板已逻辑删除导致 JOIN 不到 ldc」的记录，改为用含删除快照的批量查询再筛
        if (couponType != null) {
            couponQuery.and(w -> w.eq("ldc.coupon_type", couponType)
                    .or(sub -> sub.isNull("ldc.id").isNotNull("ldcsf.coupon_id")));
        }
        couponQuery.orderByDesc("ldcsf.created_time");
        List<LifeDiscountCouponFriendRuleVo> couponList = isReceivedByMe
                ? lifeDiscountCouponStoreFriendMapper.getReceivedSendFriendCouponList(couponQuery)
                : lifeDiscountCouponStoreFriendMapper.getReceivedSendFriendCouponListwzhy(couponQuery);

        mergeCouponTemplatesIncludeDeleted(couponList, couponType);
        fillStoreAvatar(couponList);
        return couponList;
    }

    /**
     * 使用单表直查（含 delete_flag=1 的已删模板），覆盖/补全列表中的券属性，避免商家逻辑删除模板后好友记录无法展示券信息。
     * 当传入 couponTypeFilter 时，在补全后按模板真实 coupon_type 再过滤（兼容 JOIN 不到 ldc 的行）。
     */
    private void mergeCouponTemplatesIncludeDeleted(List<LifeDiscountCouponFriendRuleVo> list, Integer couponTypeFilter) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        List<Integer> couponIds = list.stream()
                .map(LifeDiscountCouponFriendRuleVo::getCouponId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (couponIds.isEmpty()) {
            return;
        }
        List<LifeDiscountCoupon> templates = lifeDiscountCouponMapper.selectByIdsIncludeDeleted(couponIds);
        Map<Integer, LifeDiscountCoupon> byId = templates.stream()
                .collect(Collectors.toMap(LifeDiscountCoupon::getId, t -> t, (a, b) -> a));
        for (LifeDiscountCouponFriendRuleVo vo : list) {
            Integer cid = vo.getCouponId();
            if (cid == null) {
                continue;
            }
            LifeDiscountCoupon t = byId.get(cid);
            if (t != null) {
                applyDiscountCouponTemplateToFriendRuleVo(vo, t);
            }
        }
        if (couponTypeFilter != null) {
            list.removeIf(vo -> {
                LifeDiscountCoupon t = byId.get(vo.getCouponId());
                return t == null || !couponTypeFilter.equals(t.getCouponType());
            });
        }
    }

    private void applyDiscountCouponTemplateToFriendRuleVo(LifeDiscountCouponFriendRuleVo vo, LifeDiscountCoupon t) {
        vo.setCouponName(t.getName());
        vo.setNominalValue(t.getNominalValue());
        vo.setMinimumSpendingAmount(t.getMinimumSpendingAmount());
        vo.setExpirationDate(t.getExpirationDate());
        vo.setLongTermValid(t.getLongTermValid());
        vo.setCouponType(t.getCouponType());
        vo.setDiscountRate(t.getDiscountRate());
        Date valid = localDateToDate(t.getValidDate());
        vo.setEndDate(valid);
        vo.setValidDate(valid);
        vo.setBeginGetDate(localDateToDate(t.getBeginGetDate()));
        vo.setEndGetDate(localDateToDate(t.getEndGetDate()));
    }

    private static Date localDateToDate(LocalDate d) {
        if (d == null) {
            return null;
        }
        return Date.from(d.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 批量查询商户头像并填充到结果中（对方店铺展示对方商户头像，不展示当前登录人自己）
     * 优先按「对方 store_user.id」取 head_img；缺失时再按对方店铺 id 取店内主号等头像。
     */
    private void fillStoreAvatar(List<LifeDiscountCouponFriendRuleVo> couponList) {
        if (CollectionUtils.isEmpty(couponList)) {
            return;
        }

        List<Integer> counterpartyUserIds = couponList.stream()
                .map(LifeDiscountCouponFriendRuleVo::getCounterpartyStoreUserId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        Map<Integer, String> userIdToHeadImg = new HashMap<>();
        if (!counterpartyUserIds.isEmpty()) {
            LambdaQueryWrapper<StoreUser> byId = new LambdaQueryWrapper<>();
            byId.in(StoreUser::getId, counterpartyUserIds).eq(StoreUser::getDeleteFlag, 0);
            for (StoreUser u : storeUserMapper.selectList(byId)) {
                if (u.getHeadImg() != null && !u.getHeadImg().trim().isEmpty()) {
                    userIdToHeadImg.put(u.getId(), u.getHeadImg());
                }
            }
        }

        List<Integer> storeIdsForFallback = couponList.stream()
                .filter(vo -> {
                    Integer uid = vo.getCounterpartyStoreUserId();
                    if (uid != null && userIdToHeadImg.containsKey(uid)) {
                        return false;
                    }
                    return vo.getStoreId() != null;
                })
                .map(LifeDiscountCouponFriendRuleVo::getStoreId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        Map<Integer, String> storeAvatarMap = new HashMap<>();
        if (!storeIdsForFallback.isEmpty()) {
            LambdaQueryWrapper<StoreUser> userWrapper = new LambdaQueryWrapper<>();
            userWrapper.in(StoreUser::getStoreId, storeIdsForFallback)
                    .eq(StoreUser::getDeleteFlag, 0)
                    .isNotNull(StoreUser::getHeadImg)
                    .ne(StoreUser::getHeadImg, "")
                    .orderByAsc(StoreUser::getAccountType)
                    .orderByAsc(StoreUser::getId);
            for (StoreUser user : storeUserMapper.selectList(userWrapper)) {
                if (user.getStoreId() == null || user.getHeadImg() == null || user.getHeadImg().trim().isEmpty()) {
                    continue;
                }
                Integer storeId = user.getStoreId();
                if (!storeAvatarMap.containsKey(storeId)) {
                    storeAvatarMap.put(storeId, user.getHeadImg());
                } else if (user.getAccountType() != null && user.getAccountType() == 1) {
                    storeAvatarMap.put(storeId, user.getHeadImg());
                }
            }
        }

        for (LifeDiscountCouponFriendRuleVo vo : couponList) {
            Integer uid = vo.getCounterpartyStoreUserId();
            if (uid != null) {
                String byUser = userIdToHeadImg.get(uid);
                if (byUser != null) {
                    vo.setImgUrl(byUser);
                    continue;
                }
            }
            if (vo.getStoreId() != null) {
                String byStore = storeAvatarMap.get(vo.getStoreId());
                if (byStore != null) {
                    vo.setImgUrl(byStore);
                }
            }
        }
    }

    private void appendFriendSenderFilter(QueryWrapper<LifeDiscountCouponFriendRuleDetailVo> queryWrapper, String friendStoreUserId) {
        if (friendStoreUserId == null) {
            queryWrapper.eq("1", "0");
            return;
        }
        String t = friendStoreUserId.trim();
        if (t.isEmpty()) {
            queryWrapper.eq("1", "0");
            return;
        }
        try {
            applyLdcsfSenderMerchantFilter(queryWrapper, Integer.parseInt(t));
        } catch (NumberFormatException e) {
            queryWrapper.eq("1", "0");
        }
    }

    /**
     * 构建基础查询条件（与 {@code life_discount_coupon_store_friend} 四列语义对齐：
     * 我收到的 → {@code receiver_store_id} 或旧列 {@code store_user_id}；
     * 我送出的 → {@code sender_user_id} 或旧列 {@code friend_store_user_id}）。
     *
     * @param isReceivedByMe true=我收到的，false=我送出的
     * @param storeUserId     当前登录账号 store_user.id
     * @param storeName       对方店铺名称（模糊，对应联表 si.store_name）
     * @return QueryWrapper
     */
    private QueryWrapper<LifeDiscountCouponFriendRuleVo> buildBaseQueryWrapper(boolean isReceivedByMe, String storeUserId, String storeName) {
        QueryWrapper<LifeDiscountCouponFriendRuleVo> queryWrapper = new QueryWrapper<>();
        if (isReceivedByMe) {
            StoreUser storeUser = storeUserMapper.selectById(storeUserId);
            if (storeUser != null && storeUser.getStoreId() != null) {
                applyLdcsfReceiverStoreFilter(queryWrapper, storeUser.getStoreId());
            } else {
                queryWrapper.eq("1", "0");
                log.error("buildBaseQueryWrapper 查询不到店铺用户，storeUserId={}", storeUserId);
            }
        } else {
            try {
                applyLdcsfSenderMerchantFilter(queryWrapper, Integer.parseInt(storeUserId.trim()));
            } catch (NumberFormatException e) {
                queryWrapper.eq("1", "0");
                log.error("buildBaseQueryWrapper 非法 storeUserId={}", storeUserId);
            }
        }
        queryWrapper.eq("ldcsf.delete_flag", 0);
        // 店铺名称模糊查询
        if (StringUtils.isNotEmpty(storeName)) {
            queryWrapper.like("si.store_name", storeName);
        }
        return queryWrapper;
    }

    /**
     * 好评送券：用户好评且AI审核通过后，按运营活动配置的优惠券发放到用户券包。
     *
     * @param userId  评价用户ID（life用户）
     * @param storeId 店铺ID（businessId）
     * @return 发放张数，0 表示未发放
     */
    @Override
    public int issueCouponForGoodRating(Integer userId, Integer storeId) {
        if (userId == null || storeId == null) {
            return 0;
        }
        // 查询运营活动配置（评论有礼）
        Date now = new Date();
        LambdaQueryWrapper<StoreOperationalActivity> activityWrapper = new LambdaQueryWrapper<>();
        activityWrapper.eq(StoreOperationalActivity::getStoreId, storeId)
                .eq(StoreOperationalActivity::getActivityType, "COMMENT")
                .in(StoreOperationalActivity::getStatus, 5, 8)
                .le(StoreOperationalActivity::getStartTime, now)
                .ge(StoreOperationalActivity::getEndTime, now)
                .orderByDesc(StoreOperationalActivity::getId)
                .last("LIMIT 1");
        StoreOperationalActivity activity = storeOperationalActivityMapper.selectOne(activityWrapper);
        if (activity == null || activity.getCouponId() == null || activity.getCouponId() <= 0) {
            return 0;
        }
        
        // 检查参与次数限制
        Integer limit = activity.getParticipationLimit();
        if (limit != null && limit > 0) {
            // 只统计活动开始时间之后的好评，活动开始前的评论不计入参与次数
            int passedCount = commonRatingMapper.countPassedGoodRatingsByUserAndStore(
                    Long.valueOf(userId), storeId, activity.getStartTime());
            if (passedCount > limit) {
                log.info("issueCouponForGoodRating 好评送券跳过：超过运营活动参与次数 participation_limit={}, count={}, userId={}, storeId={}, activityStartTime={}",
                        limit, passedCount, userId, storeId, activity.getStartTime());
                return 0;
            }
        }

        return issueCouponForGoodRating(userId, storeId, activity.getCouponId(), activity.getCouponQuantity());
    }

    private static int resolveGoodRatingCouponCopies(Integer couponQuantity) {
        if (couponQuantity == null) {
            return 1;
        }
        if (couponQuantity < 1) {
            return 0;
        }
        return Math.min(couponQuantity, GOOD_RATING_ISSUE_COPIES_HARD_CAP);
    }

    /**
     * 好评送券：按优惠券模板 ID 发放到用户券包，扣减库存并通知。
     */
    @Override
    public int issueCouponForGoodRating(Integer userId, Integer storeId, Integer couponId) {
        return issueCouponForGoodRating(userId, storeId, couponId, null);
    }

    @Override
    public int issueCouponForGoodRating(Integer userId, Integer storeId, Integer couponId, Integer couponQuantity) {
        if (userId == null || storeId == null) {
            return 0;
        }
        if (couponId == null || couponId <= 0) {
            return 0;
        }
        int commenterUserId = userId.intValue();
        int copiesWanted = resolveGoodRatingCouponCopies(couponQuantity);

        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        LifeUser lifeUser = lifeUserMapper.selectById(commenterUserId);

        LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(couponId);
        if (coupon == null || !String.valueOf(storeId).equals(coupon.getStoreId())) {
            return 0;
        }
        if (!LifeDiscountCouponStock.hasTemplateStockRemaining(coupon.getUnlimitedQty(), coupon.getSingleQty())) {
            return 0;
        }

        ZoneId zone = ZoneId.systemDefault();
        if (!Integer.valueOf(1).equals(coupon.getLongTermValid())) {
            LocalDate beginDate = coupon.getBeginGetDate();
            if (beginDate == null) {
                beginDate = LocalDate.now(zone);
                coupon.setBeginGetDate(beginDate);
            }
            String specifiedDayStr = coupon.getSpecifiedDay();
            if (specifiedDayStr == null || specifiedDayStr.isEmpty()) {
                log.error("发放优惠券失败（非长期券缺少有效天数），userId={}, storeId={}, couponId={}", userId, storeId, couponId);
                return 0;
            }
            int days;
            try {
                days = Integer.parseInt(specifiedDayStr.trim());
            } catch (NumberFormatException e) {
                log.error("发放优惠券失败（有效天数非法），userId={}, storeId={}, couponId={}, specifiedDay={}",
                        userId, storeId, couponId, specifiedDayStr, e);
                return 0;
            }
            if (days <= 0) {
                log.error("发放优惠券失败（有效天数须>0），userId={}, storeId={}, couponId={}", userId, storeId, couponId);
                return 0;
            }
            coupon.setEndGetDate(beginDate.plusDays(days));
        }

        int grantedCoupon = 0;
        for (int i = 0; i < copiesWanted; i++) {
            if (!LifeDiscountCouponStock.hasTemplateStockRemaining(coupon.getUnlimitedQty(), coupon.getSingleQty())) {
                break;
            }
            try {
                Date receiveTime = new Date();
                LifeDiscountCouponUser lifeDiscountCouponUser = new LifeDiscountCouponUser();
                lifeDiscountCouponUser.setCouponId(coupon.getId());
                lifeDiscountCouponUser.setUserId(commenterUserId);
                lifeDiscountCouponUser.setReceiveTime(receiveTime);
                lifeDiscountCouponUser.setExpirationTime(DiscountCouponExpirationUtil.resolveLifeDiscountCouponExpiration(
                        receiveTime,
                        coupon.getLongTermValid(),
                        coupon.getSpecifiedDay(),
                        coupon.getExpirationDate(),
                        coupon.getValidDate(),
                        coupon.getEndDate(),
                        zone));
                lifeDiscountCouponUser.setStatus(Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()));
                lifeDiscountCouponUser.setDeleteFlag(0);
                lifeDiscountCouponUser.setIssueSource(3); // 3-好评送券
                lifeDiscountCouponUserMapper.insert(lifeDiscountCouponUser);
                if (!LifeDiscountCouponStock.isUnlimitedQty(coupon.getUnlimitedQty())
                        && coupon.getSingleQty() != null) {
                    coupon.setSingleQty(coupon.getSingleQty() - 1);
                }
                grantedCoupon++;
            } catch (Exception e) {
                log.error("发放优惠券失败，userId={}, storeId={}, couponId={}, index={}, error={}",
                        userId, storeId, couponId, i, e.getMessage(), e);
                break;
            }
        }

        if (grantedCoupon > 0) {
            try {
                lifeDiscountCouponMapper.updateById(coupon);
            } catch (Exception e) {
                log.error("更新优惠券模板失败 userId={}, storeId={}, couponId={}, error={}", userId, storeId, couponId, e.getMessage(), e);
            }
        }

        LifeDiscountCoupon lifeDiscountCoupon = grantedCoupon > 0 ? coupon : null;
        String couponName = grantedCoupon > 0 ? coupon.getName() : null;

        if (lifeUser != null && storeInfo != null && grantedCoupon > 0 && couponName != null) {
            LifeNotice couponNotice = new LifeNotice();
            couponNotice.setSenderId("system");
            couponNotice.setReceiverId("user_" + lifeUser.getUserPhone());

            String couponDetailText = "";
            if (lifeDiscountCoupon != null) {
                Integer cType = lifeDiscountCoupon.getCouponType();
                if (cType != null && cType == 2) {
                    BigDecimal discountRate = lifeDiscountCoupon.getDiscountRate();
                    if (discountRate != null) {
                        BigDecimal zheShu = discountRate.divide(BigDecimal.TEN, 2, RoundingMode.HALF_UP);
                        String zheShuText = zheShu.stripTrailingZeros().toPlainString();
                        couponDetailText = "（" + zheShuText + "折";
                        if (lifeDiscountCoupon.getMinimumSpendingAmount() != null) {
                            couponDetailText += "，满" + lifeDiscountCoupon.getMinimumSpendingAmount() + "可用";
                        }
                        couponDetailText += "）";
                    }
                } else {
                    if (lifeDiscountCoupon.getNominalValue() != null) {
                        couponDetailText = "（满减" + lifeDiscountCoupon.getNominalValue() + "元";
                        if (lifeDiscountCoupon.getMinimumSpendingAmount() != null) {
                            couponDetailText += "，满" + lifeDiscountCoupon.getMinimumSpendingAmount() + "可用";
                        }
                        couponDetailText += "）";
                    }
                }
            }

            String couponText = grantedCoupon > 1
                    ? "您对店铺「" + storeInfo.getStoreName() + "」的好评已通过审核，已为您发放优惠券「" + couponName + "」"
                    + couponDetailText + "共" + grantedCoupon + "张，快去我的券包查看吧~"
                    : "您对店铺「" + storeInfo.getStoreName() + "」的好评已通过审核，已为您发放优惠券「" + couponName + "」"
                    + couponDetailText + "，快去我的券包查看吧~";
            JSONObject couponJson = new JSONObject();
            couponJson.put("message", couponText);
            couponJson.put("couponType", "优惠券");
            couponJson.put("couponName", couponName);
            couponJson.put("grantCount", grantedCoupon);
            if (lifeDiscountCoupon != null) {
                couponJson.put("couponTypeValue", lifeDiscountCoupon.getCouponType());
            }
            couponNotice.setContext(couponJson.toJSONString());
            couponNotice.setNoticeType(1);
            couponNotice.setTitle("好评送优惠券");
            couponNotice.setIsRead(0);
            couponNotice.setDeleteFlag(0);
            lifeNoticeUtil.fillUserTypeAndRefId(couponNotice);
            lifeNoticeMapper.insert(couponNotice);

            try {
                WebSocketVo websocketVo = new WebSocketVo();
                websocketVo.setSenderId("system");
                websocketVo.setReceiverId("user_" + lifeUser.getUserPhone());
                websocketVo.setCategory("notice");
                websocketVo.setNoticeType("1");
                websocketVo.setIsRead(0);
                websocketVo.setText(JSONObject.from(couponNotice).toJSONString());
                webSocketProcess.sendMessage("user_" + lifeUser.getUserPhone(), JSONObject.from(websocketVo).toJSONString());
            } catch (Exception e) {
                log.error("好评送优惠券 WebSocket 推送失败，userId={}, storeId={}, couponId={}, error={}", userId, storeId, couponId, e.getMessage(), e);
            }
        }

        return grantedCoupon;
    }
}
