package com.czg.service.market.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopUserService;
import com.czg.constant.TableValueConstant;
import com.czg.exception.CzgException;
import com.czg.market.entity.MkConsumeDiscountRandom;
import com.czg.market.service.MkConsumeDiscountService;
import com.czg.market.vo.MkConsumeDiscountVO;
import com.czg.order.entity.OrderInfo;
import com.czg.market.service.OrderInfoService;
import com.czg.service.market.enums.OrderStatusEnums;
import com.czg.utils.AssertUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkShopConsumeDiscountRecord;
import com.czg.market.service.MkShopConsumeDiscountRecordService;
import com.czg.service.market.mapper.MkShopConsumeDiscountRecordMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;

import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

/**
 * 新客立减减免记录 服务层实现。
 *
 * @author zs
 * @since 2025-09-17
 */
@Slf4j
@DubboService
public class MkShopConsumeDiscountRecordServiceImpl extends ServiceImpl<MkShopConsumeDiscountRecordMapper, MkShopConsumeDiscountRecord> implements MkShopConsumeDiscountRecordService {
    @Resource
    private MkConsumeDiscountService consumeDiscountService;
    @DubboReference
    private ShopUserService shopUserService;
    @Resource
    private OrderInfoService orderInfoService;

    @Override
    public void checkDiscount(Long shopId, Long userId, Long orderId, BigDecimal amount) {
        MkConsumeDiscountVO consumeDiscountVO = canUse(shopId, userId);
        MkShopConsumeDiscountRecord discountRecord = getOne(new QueryWrapper().eq(MkShopConsumeDiscountRecord::getShopId, shopId).eq(MkShopConsumeDiscountRecord::getOrderId, orderId));
        AssertUtil.isNull(discountRecord, "新客立减记录不存在");
        AssertUtil.isTrue(amount.compareTo(consumeDiscountVO.getDiscountAmount()) != 0, "减免金额错误");
    }

    private MkConsumeDiscountVO canUse(Long shopId, Long userId) {
        MkConsumeDiscountVO consumeDiscountVO = consumeDiscountService.detail(shopId);
        if (consumeDiscountVO.getIsEnable() != 1) {
            throw new CzgException("新客立减未开启");
        }

        DateTime now = DateUtil.date();

        if (!now.isAfterOrEquals(DateUtil.date(consumeDiscountVO.getStartTime())) || !now.isBeforeOrEquals(DateUtil.date(consumeDiscountVO.getEndTime()))) {
            throw new CzgException("此时间段未开启新客立减");
        }

        // 随机金额（概率加起来是100）
        List<MkConsumeDiscountRandom> randomList = consumeDiscountVO.getRandomDiscountList();
        if ("RANDOM".equals(consumeDiscountVO.getDiscountType()) && (randomList == null || randomList.isEmpty())) {
            throw new CzgException("随机立减配置错误");
        }
        ShopUser shopUser = shopUserService.getShopUserInfo(shopId, userId);
        boolean exists = orderInfoService.exists(new QueryWrapper().eq(OrderInfo::getUserId, shopUser.getUserId())
                .eq(OrderInfo::getShopId, shopUser.getSourceShopId()).eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()));
        AssertUtil.isTrue(exists, "新客立减仅限新用户使用");


        boolean exists1 = exists(new QueryWrapper().eq(MkShopConsumeDiscountRecord::getShopId, shopId).eq(MkShopConsumeDiscountRecord::getShopUserId, shopUser.getId())
                .eq(MkShopConsumeDiscountRecord::getIsUse, 1));

        AssertUtil.isTrue(exists1, "新客立减已使用");

        return consumeDiscountVO;
    }

    @Override
    public void useDiscount(Long shopUserId, Long orderId, BigDecimal amount) {
        AssertUtil.isTrue(shopUserId == null || orderId == null || amount == null, "参数不能为空");
//        ShopUser shopUser = shopUserService.getById(shopUserId);

        MkShopConsumeDiscountRecord discountRecord = getOne(new QueryWrapper()
                .eq(MkShopConsumeDiscountRecord::getShopUserId, shopUserId));
        AssertUtil.isNull(discountRecord, "减免记录不存在");
        AssertUtil.isTrue(discountRecord.getIsUse() == 1, "减免记录已使用");
        AssertUtil.isTrue(discountRecord.getAmount().compareTo(amount) != 0, "减免金额不同");

        boolean flag = updateChain().eq(MkShopConsumeDiscountRecord::getId, discountRecord.getId())
                .eq(MkShopConsumeDiscountRecord::getIsUse, 0)
                .set(MkShopConsumeDiscountRecord::getOrderId, orderId)
                .set(MkShopConsumeDiscountRecord::getIsUse, 1).update();
        AssertUtil.isTrue(!flag, "修改失败");
    }

    @Override
    public boolean isNewUser(ShopUser shopUser, Long shopId) {
        MkShopConsumeDiscountRecord discountRecord = getOne(new QueryWrapper().eq(MkShopConsumeDiscountRecord::getShopId, shopId)
                .eq(MkShopConsumeDiscountRecord::getIsUse, 1)
                .eq(MkShopConsumeDiscountRecord::getShopUserId, shopUser.getId()));
        boolean exists = orderInfoService.exists(new QueryWrapper().eq(OrderInfo::getUserId, shopUser.getUserId())
                .eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()));
        return !exists && discountRecord == null;
    }

    @Override
    public MkShopConsumeDiscountRecord getDiscount(Long shopId, Long userId, Long orderId) {
        ShopUser shopUser = shopUserService.getUserInfo(shopId, userId);
        AssertUtil.isTrue(shopUser == null, "用户不存在");
        boolean newUser = isNewUser(shopUser, shopId);
        if (!newUser) {
//            throw new CzgException("新客立减仅新用户可用");
            log.info("新客立减仅限新用户使用");
            return null;
        }


        try {
            MkConsumeDiscountVO consumeDiscountVO = canUse(shopId, userId);

            if (consumeDiscountVO.getIsEnable() != 1) {
                return null;
            }

            DateTime now = DateUtil.date();

            if (!now.isAfterOrEquals(DateUtil.date(consumeDiscountVO.getStartTime())) || !now.isBeforeOrEquals(DateUtil.date(consumeDiscountVO.getEndTime()))) {
                log.info("此时间段未开启新客立减");
                return null;
            }
            MkShopConsumeDiscountRecord discountRecord = getOne(new QueryWrapper().eq(MkShopConsumeDiscountRecord::getShopId, shopId)
                    .eq(MkShopConsumeDiscountRecord::getOrderId, orderId)
                    .eq(MkShopConsumeDiscountRecord::getIsUse, 0)
                    .eq(MkShopConsumeDiscountRecord::getShopUserId, shopUser.getId()));
            if (discountRecord != null) {
                boolean isUp = false;
                if (consumeDiscountVO.getUpdateTime() != null && consumeDiscountVO.getUpdateTime().isBefore(discountRecord.getUpdateTime())) {
                    BigDecimal deductionAmount = deductionAmount(consumeDiscountVO);
                    discountRecord.setAmount(deductionAmount);
                    isUp = true;
                }
                if (discountRecord.getOrderId() == null && orderId != null) {
                    discountRecord.setOrderId(orderId);
                    isUp = true;
                }
                if (isUp) {
                    updateById(discountRecord);
                }
                return discountRecord;
            }

            MkShopConsumeDiscountRecord shopConsumeDiscountRecord = new MkShopConsumeDiscountRecord();
            shopConsumeDiscountRecord.setShopId(shopId);
            shopConsumeDiscountRecord.setShopUserId(shopUser.getId());
            shopConsumeDiscountRecord.setOrderId(orderId);
            shopConsumeDiscountRecord.setConsumeDiscountId(consumeDiscountVO.getId());

            BigDecimal deductionAmount = deductionAmount(consumeDiscountVO);
            if (deductionAmount.compareTo(BigDecimal.ZERO) == 0) {
                return null;
            }
            shopConsumeDiscountRecord.setAmount(deductionAmount);
            save(shopConsumeDiscountRecord);
            return shopConsumeDiscountRecord;
        } catch (Exception e) {
            log.info(e.getMessage());
            return null;
        }
    }


    private BigDecimal deductionAmount(MkConsumeDiscountVO consumeDiscountVO) {
        // 固定金额
        if (TableValueConstant.ConsumeDiscount.DiscountType.FIXED.getCode().equals(consumeDiscountVO.getDiscountType())) {
            return consumeDiscountVO.getDiscountAmount();
        }

        // 随机金额（概率加起来是100）
        List<MkConsumeDiscountRandom> randomList = consumeDiscountVO.getRandomDiscountList();
        if (randomList == null || randomList.isEmpty()) {
            throw new CzgException("随机立减配置错误");
        }

        // 生成 1~100 的随机数
        int rand = new Random().nextInt(100) + 1;
        int current = 0;

        for (MkConsumeDiscountRandom item : randomList) {
            int prob = item.getProbability().intValue();
            current += prob;
            if (rand <= current) {
                return item.getAmount();
            }
        }
        return BigDecimal.ZERO;
    }
}
