package com.yami.shop.user.api.listener;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.param.OrderParam;
import com.yami.shop.bean.event.ConfirmOrderEvent;
import com.yami.shop.bean.event.PlatformConfirmOrderEvent;
import com.yami.shop.bean.event.ScoreConfirmOrderEvent;
import com.yami.shop.bean.dto.XsbMemberDiscountInfo;
import com.yami.shop.bean.model.Category;
import com.yami.shop.bean.model.UserExtension;
import com.yami.shop.bean.order.ConfirmOrderOrder;
import com.yami.shop.bean.param.ScoreConfigParam;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.util.Arith;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.CategoryService;
import com.yami.shop.service.SysConfigService;
import com.yami.shop.service.UserExtensionService;
import com.yami.shop.service.XsbMemberSupportService;
import com.yami.shop.user.comment.dao.UserLevelMapper;
import com.yami.shop.user.comment.model.UserLevel;
import com.yami.shop.user.comment.util.CategoryScale;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.swing.text.StyledEditorKit;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 确认订单监听器（会员折扣和等级折扣）
 */
@Component("userConfirmOrderListener")
@AllArgsConstructor
public class ConfirmOrderListener {

    private final UserExtensionService userExtensionService;
    private final SysConfigService sysConfigService;
    private final UserLevelMapper userLevelMapper;
    private final CategoryService categoryService;
    private final XsbMemberSupportService xsbMemberSupportService;

    /**
     * 积分支付确认订单监听器
     */
    @EventListener(ScoreConfirmOrderEvent.class)
    @Order(ConfirmOrderOrder.SCORE)
    public void scoreSubmitOrderListener(ScoreConfirmOrderEvent event) {
        System.out.println(JSONObject.toJSONString(event));
// 获取用户扩展信息
//        UserExtension extension = userExtensionService.getOne(
//                new LambdaQueryWrapper<UserExtension>().eq(UserExtension::getUserId, SecurityUtils.getUser().getUserId()));
// 获取积分配置
//        ScoreConfigParam scoreParam = sysConfigService.getSysConfigObject(Constant.SCORE_CONFIG,ScoreConfigParam.class);
//        if(Objects.nonNull(scoreParam)  && scoreParam.getShopScoreSwitch() != null && !scoreParam.getShopScoreSwitch()){
//            return;
//        }
//        ShopCartOrderMergerDto shopCartOrderMergerDto = event.getShopCartOrderMergerDto();
//        OrderParam orderParam = event.getOrderParam();
//        if(orderParam.getUserUseScore() != null && orderParam.getUserUseScore() < 0 && extension.getScore() < 0){
//            return;
//        }
// 计算总积分抵扣金额
//        double totalScoreAmount = 0.0;
//        List<Category> categories = categoryService.listByShopId(Constant.PLATFORM_SHOP_ID);
//        Map<Long, Double> categoryMap = CategoryScale.getScaleByCategory(categories,scoreParam,0);
// 根据配置范围计算
//        if(scoreParam.getUseDiscountRange() == 0){
// 计算实际总金额
//            double actualTotal = Arith.sub(shopCartOrderMergerDto.getActualTotal(),shopCartOrderMergerDto.getTotalTransfee());
//            totalScoreAmount = Arith.div(Arith.mul(actualTotal, scoreParam.getUseDiscount()), 100);
//        }else{
// 遍历所有商品项
//            for (ShopCartItemDto shopCartItem : event.getAllCartItem()) {
//                if(!categoryMap.containsKey(shopCartItem.getCategoryId())) {
//                    continue;
//                }
// 计算商品实际金额
//                double actualTotal = Arith.sub(Arith.sub(shopCartItem.getProductTotalAmount(), shopCartItem.getShareReduce()),shopCartItem.getPlatformShareReduce());
//                double scoreReduce = Arith.div(Arith.mul(actualTotal, categoryMap.get(shopCartItem.getCategoryId())),100);
//                totalScoreAmount = Arith.add(totalScoreAmount,scoreReduce);
//            }
//        }
// 计算可用积分
//        int canUseScore = (int) Arith.mul(totalScoreAmount, scoreParam.getShopUseScore());
////        totalScoreAmount = Arith.div(canUseScore, scoreParam.getShopUseScore(),2);
//        Integer userUseScore = extension.getScore();
//        Integer totalUsableScore = extension.getScore();
// 判断是否使用积分支付
//        if(orderParam.getUserUseScore() != null && orderParam.getIsScorePay() == 1 && orderParam.getUserUseScore() >= 0){
//            userUseScore = Math.min(orderParam.getUserUseScore(),userUseScore);
//        }else{
//            userUseScore = 0;
//        }
//        double scale = 1.0;
//        if(userUseScore < canUseScore){
//            scale = Arith.div(userUseScore, canUseScore);
//        }
//        int maxScore = Math.min(totalUsableScore,canUseScore);
//        userUseScore = Math.min(userUseScore, canUseScore);
// 调整积分使用量
//        if(scoreParam.getShopUseScore() > 100){
//            userUseScore = userUseScore - userUseScore % 10;
//            maxScore = maxScore - maxScore % 10;
//        }
// 计算总积分金额
//        totalScoreAmount = Arith.div(userUseScore,scoreParam.getShopUseScore(),2);
//        userUseScore = (int) Arith.mul(totalScoreAmount, scoreParam.getShopUseScore());
// 遍历店铺订单
//        List<ShopCartOrderDto> shopCartOrders = shopCartOrderMergerDto.getShopCartOrders();
//        double totalScoreReduce = 0.0;
//        int totalScore = 0;
// 会员折扣计算说明
//        for (int shopIndex = 0; shopIndex < shopCartOrders.size(); shopIndex++) {
//            ShopCartOrderDto shopCartOrder = shopCartOrders.get(shopIndex);
//            double reduceSum = 0.0;
//            int shopScore = 0;
//            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
//            for (int discountIndex = 0; discountIndex < shopCartItemDiscounts.size(); discountIndex++) {
//                List<ShopCartItemDto> shopCartItems = shopCartItemDiscounts.get(discountIndex).getShopCartItems();
//                for (int itemIndex = 0; itemIndex< shopCartItems.size(); itemIndex++) {
//                    ShopCartItemDto shopCartItem = shopCartItems.get(itemIndex);
//                    double scoreReduceProd = 0.0;
// 判断是否为最后一个商品项
//                    boolean isEnd =  shopIndex == shopCartOrders.size() - 1 && discountIndex ==shopCartItemDiscounts.size() - 1 && itemIndex == shopCartItems.size() - 1;
// 根据范围计算积分抵扣
//                    if(scoreParam.getUseDiscountRange() == 0){
//                        scoreReduceProd = Arith.div(Arith.mul(shopCartItem.getActualTotal(),scoreParam.getUseDiscount()),100,2);
//                    }else if(categoryMap.containsKey(shopCartItem.getCategoryId())){
//                        scoreReduceProd = Arith.div(Arith.mul(shopCartItem.getActualTotal(),categoryMap.get(shopCartItem.getCategoryId())),100,2);
//                    }
//                    int useScore = (int) Arith.mul(Arith.round(Arith.mul(scoreReduceProd,scale),2), scoreParam.getShopUseScore());
//                    scoreReduceProd = Arith.div(useScore, scoreParam.getShopUseScore(),2);
// 判断是否超出总额度
//                    if(Arith.add(totalScoreReduce,scoreReduceProd) > totalScoreAmount || isEnd){
// 计算实际使用积分
//                        useScore = userUseScore - totalScore - shopScore;
//                        scoreReduceProd = Arith.sub(totalScoreAmount ,totalScoreReduce);
//                    }
//
//                    totalScoreReduce = Arith.add(totalScoreReduce, scoreReduceProd);
//                    reduceSum = Arith.add(reduceSum, scoreReduceProd);
//                    shopScore += useScore;
//                    if (orderParam.getIsScorePay() != null && orderParam.getIsScorePay() == 1) {
// 设置积分支付信息
//                        shopCartItem.setPlatformShareReduce(Arith.add(platformReduce, scoreReduceProd));
//                        shopCartItem.setScorePayReduce(scoreReduceProd);
//                        shopCartItem.setScorePrice(useScore);
//                        shopCartItem.setShareReduce(Arith.add(Arith.round(shopCartItem.getShareReduce(),2),scoreReduceProd));
//                        shopCartItem.setActualTotal(Arith.sub(shopCartItem.getActualTotal(),scoreReduceProd));
//                    }
//                }
//            }
// 设置店铺积分抵扣
//            shopCartOrder.setScoreReduce(reduceSum);
//            shopCartOrder.setActualTotal(Arith.sub(shopCartOrder.getActualTotal(),reduceSum));
// 更新店铺优惠金额
//            shopCartOrder.setShopReduce(Arith.add(shopCartOrder.getShopReduce(),reduceSum));
// 设置平台优惠金额
//            shopCartOrder.setPlatformAmount(Arith.add(shopCartOrder.getPlatformAmount(),reduceSum));
//            totalScore += shopScore;
//            if (orderParam.getIsScorePay() != null && orderParam.getIsScorePay() == 1) {
//                shopCartOrder.setUseScore(shopScore);
//            }
//        }
// 设置合并订单积分信息
//        shopCartOrderMergerDto.setTotalScoreAmount(totalScoreReduce);
//        shopCartOrderMergerDto.setShopUseScore(scoreParam.getShopUseScore());
//        shopCartOrderMergerDto.setTotalUsableScore(totalScore);
//        shopCartOrderMergerDto.setActualTotal(Arith.sub(shopCartOrderMergerDto.getActualTotal(),totalScoreReduce));
//        shopCartOrderMergerDto.setOrderReduce(Arith.add(shopCartOrderMergerDto.getOrderReduce(),totalScoreReduce));
//        shopCartOrderMergerDto.setMaxUsableScore(maxScore);
//        if (orderParam.getIsScorePay() != null && orderParam.getIsScorePay() == 1) {
//            shopCartOrderMergerDto.setScorePrice(totalScore);
//        }
    }

    /**
     * Apply member discount for XSB mall items only.
     */
    @EventListener(ConfirmOrderEvent.class)
    @Order(ConfirmOrderOrder.MEMBER)
    public void memberDiscountConfirmOrderListener(ConfirmOrderEvent event) {
        ShopCartOrderDto shopCartOrderDto = event.getShopCartOrderDto();
        List<ShopCartItemDto> xsbItems = event.getShopCartItems().stream()
                .filter(xsbMemberSupportService::isXsbItem)
                .filter(item -> Boolean.TRUE.equals(item.getIsMember()))
                .filter(item -> item.getMemberPrice() != null)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(xsbItems)) {
            return;
        }
        Double memberDiscountRate = resolveMemberDiscountRate();
        double memberReduce = 0.0;
        for (ShopCartItemDto shopCartItem : xsbItems) {
            double productTotal = shopCartItem.getProductTotalAmount() == null ? 0.0 : shopCartItem.getProductTotalAmount();
            double memberTotal = Arith.mul(shopCartItem.getMemberPrice(), shopCartItem.getProdCount());
            double reduceAmount = Arith.round(Arith.sub(productTotal, memberTotal), 2);
            if (reduceAmount < 0) {
                reduceAmount = 0.0;
            }
            if (reduceAmount > productTotal) {
                reduceAmount = productTotal;
            }
            if (reduceAmount <= 0) {
                shopCartItem.setMemberDiscountShareAmount(0.0);
                continue;
            }
            shopCartItem.setMemberDiscountShareAmount(reduceAmount);
            shopCartItem.setShareReduce(Arith.add(shopCartItem.getShareReduce(), reduceAmount));
            shopCartItem.setActualTotal(Arith.sub(shopCartItem.getActualTotal(), reduceAmount));
            memberReduce = Arith.add(memberReduce, reduceAmount);
        }
        if (memberReduce <= 0) {
            return;
        }
        shopCartOrderDto.setMemberDiscountAmount(memberReduce);
        shopCartOrderDto.setMemberDiscountDesc("Member discount");
        shopCartOrderDto.setMemberDiscountRate(memberDiscountRate);
        shopCartOrderDto.setMemberBenefitDesc(buildMemberBenefitDesc(memberDiscountRate));
        shopCartOrderDto.setActualTotal(Arith.sub(shopCartOrderDto.getActualTotal(), memberReduce));
        shopCartOrderDto.setShopReduce(Arith.add(shopCartOrderDto.getShopReduce(), memberReduce));
    }

    private Double resolveMemberDiscountRate() {
        XsbMemberDiscountInfo memberInfo = xsbMemberSupportService.getMemberDiscountInfo(SecurityUtils.getUser().getUserId());
        if (memberInfo == null || !Boolean.TRUE.equals(memberInfo.getMember())) {
            return null;
        }
        Double discountRate = memberInfo.getDiscountRate();
        if (discountRate == null || discountRate <= 0 || discountRate >= 1) {
            return null;
        }
        return discountRate;
    }

    private String buildMemberBenefitDesc(Double memberDiscountRate) {
        if (memberDiscountRate == null) {
            return "会员权益";
        }
        BigDecimal discountValue = BigDecimal.valueOf(memberDiscountRate).multiply(BigDecimal.TEN).stripTrailingZeros();
        return "会员权益（" + discountValue.toPlainString() + "折）";
    }

    /**
     * Apply original level discount logic.
     */
    @EventListener(PlatformConfirmOrderEvent.class)
    @Order(ConfirmOrderOrder.LEVEL)
    public void levelSubmitOrderListener(PlatformConfirmOrderEvent event) {
        UserExtension extension = userExtensionService.getOne(
                new LambdaQueryWrapper<UserExtension>().eq(UserExtension::getUserId, SecurityUtils.getUser().getUserId()));
        if (extension == null) {
            return;
        }
        UserLevel level = userLevelMapper.selectOneAndCategory(extension);
        if (level == null || level.getDiscount() > 10) {
            return;
        }
        ShopCartOrderMergerDto shopCartOrderMergerDto = event.getShopCartOrderMergerDto();
        List<ShopCartOrderDto> shopCartOrders = shopCartOrderMergerDto.getShopCartOrders();
        // 初始化用户等级
        if (extension.getLevel() == null) {
            extension.setLevel(Constant.USER_LEVEL_INIT);
        }
        double levelDiscount = 0.0;
        double freeTransfee = 0.0;
//        double levelDiscountActualTotal= 0.0;
        double discount = Arith.sub(10, level.getDiscount());

        // 获取等级分类配置
        List<Long> categoryIds = level.getCategoryIds();
        Map<Long, Long> categoryMap = new HashMap<>(100);
        if (CollectionUtils.isNotEmpty(categoryIds)) {
            categoryIds.forEach(categoryId -> categoryMap.put(categoryId, categoryId));
        }
        // 计算等级优惠总额
        double maxlevelFeeTotal = getLevelFeeTotal(shopCartOrders, level, categoryMap);
        // 遍历店铺订单
        for (int shopIndex = 0; shopIndex < shopCartOrders.size(); shopIndex++) {
            ShopCartOrderDto shopCartOrder = shopCartOrders.get(shopIndex);
            // 判断店铺范围
            if (level.getDiscountRange() == 1 && !Objects.equals(shopCartOrder.getShopId(), 1L)) {
                continue;
            }
            double reduceSum = 0.0;
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
            for (int discountIndex = 0; discountIndex < shopCartItemDiscounts.size(); discountIndex++) {
                List<ShopCartItemDto> shopCartItems = shopCartItemDiscounts.get(discountIndex).getShopCartItems();
                for (int itemIndex = 0; itemIndex < shopCartItems.size(); itemIndex++) {
                    ShopCartItemDto shopCartItem = shopCartItems.get(itemIndex);
                    double prodDiscount = 0.0;
                    // 判断是否为最后一个商品
                    boolean isEnd = shopIndex == shopCartOrders.size() - 1 && discountIndex == shopCartItemDiscounts.size() - 1 && itemIndex == shopCartItems.size() - 1;
                    // 计算商品折扣
                    if (level.getDiscountType() == 0 || categoryMap.containsKey(shopCartItem.getCategoryId())) {
                        prodDiscount = Arith.div(Arith.mul(shopCartItem.getActualTotal(), discount), 10, 2);
                        if (isEnd || Arith.add(Arith.add(levelDiscount, reduceSum), prodDiscount) > maxlevelFeeTotal) {
                            // 调整最后一个商品的折扣金额
                            prodDiscount = Arith.sub(Arith.sub(maxlevelFeeTotal, levelDiscount), reduceSum);
                        }
                    }
                    // 设置平台分摊优惠
                    shopCartItem.setPlatformShareReduce(Arith.add(shopCartItem.getPlatformShareReduce(), prodDiscount));
                    reduceSum = Arith.add(reduceSum, Arith.round(prodDiscount, 2));
                }
            }
            // 设置等级优惠金额
            shopCartOrder.setLevelReduce(reduceSum);
            levelDiscount = Arith.add(levelDiscount, reduceSum);
            // 免运费处理
            //&& level.getCategoryIds()
            if (Objects.equals(shopCartOrder.getShopId(), Constant.MAIN_SHOP) && level.getIsFreeFee() == 1) {
                freeTransfee = shopCartOrder.getTransfee();
                shopCartOrder.setFreeTransfee(shopCartOrder.getTransfee());
                shopCartOrder.setTransfee(0.0);
            }
        }
        shopCartOrderMergerDto.setTotalLevelAmount(levelDiscount);
        // 设置免运费金额
        shopCartOrderMergerDto.setFreeTransfee(freeTransfee);
    }

    /**
     * 计算等级优惠总额
     *
     * @param shopCartOrders 店铺订单列表
     * @param level 用户等级
     * @param categoryMap 分类映射
     * @return 等级优惠总额
     */
    private double getLevelFeeTotal(List<ShopCartOrderDto> shopCartOrders, UserLevel level, Map<Long, Long> categoryMap) {
        double totalFee = 0.0;
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            // 判断店铺范围
            if (level.getDiscountRange() == 1 && !Objects.equals(shopCartOrder.getShopId(), 1L)) {
                continue;
            }
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
                for (ShopCartItemDto shopCartItem : shopCartItems) {
                    // 判断是否在等级分类范围内
                    if (level.getDiscountType() == 0 || categoryMap.containsKey(shopCartItem.getCategoryId())) {
                        totalFee = Arith.add(totalFee, shopCartItem.getActualTotal());
                    }
                }
            }
        }
//        return Arith.div(totalFee,level.getDiscount(),2);
        return Arith.div(Arith.mul(totalFee, Arith.sub(10, level.getDiscount())), 10, 2);
    }
}
