package com.starry.admin.modules.order.service.support;

import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import com.starry.admin.modules.order.module.vo.ClerkEstimatedRevenueVo;
import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo;
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 计算店员预计收入的工具类，供订单生命周期与订单查询等场景复用。
 */
@Slf4j
@Component
public class ClerkRevenueCalculator {

    @Resource
    private IPlayClerkUserInfoService playClerkUserInfoService;

    @Resource
    private IPlayCouponDetailsService playCouponDetailsService;

    public ClerkEstimatedRevenueVo calculateEstimatedRevenue(
            String clerkId,
            List<String> couponIds,
            String placeType,
            String firstOrder,
            BigDecimal orderAmount) {
        PlayClerkLevelInfoEntity levelInfo = playClerkUserInfoService.queryLevelCommission(clerkId);
        BigDecimal baseAmount = orderAmount == null ? BigDecimal.ZERO : orderAmount;
        ClerkEstimatedRevenueVo estimatedRevenueVo = new ClerkEstimatedRevenueVo();

        if (levelInfo == null) {
            log.warn("店员{}缺少等级提成配置，预计收益按0处理", clerkId);
            estimatedRevenueVo.setRevenueRatio(0);
            estimatedRevenueVo.setRevenueAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
            return estimatedRevenueVo;
        }

        boolean fallbackToOther = false;
        OrderConstant.PlaceType placeTypeEnum;
        try {
            placeTypeEnum = OrderConstant.PlaceType.fromCode(placeType);
        } catch (IllegalArgumentException ex) {
            fallbackToOther = true;
            placeTypeEnum = OrderConstant.PlaceType.OTHER;
            log.warn("无法识别的下单类型，placeType={}，clerkId={}。已按其他类型处理。", placeType, clerkId, ex);
        }

        switch (placeTypeEnum) {
            case SPECIFIED: // 指定单
                fillRegularOrderRevenue(clerkId, firstOrder, baseAmount, levelInfo, estimatedRevenueVo);
                break;
            case RANDOM: // 随机单
                fillRandomOrderRevenue(clerkId, firstOrder, baseAmount, levelInfo, estimatedRevenueVo);
                break;
            case REWARD: // 打赏单
                fillRewardOrderRevenue(clerkId, firstOrder, baseAmount, levelInfo, estimatedRevenueVo);
                break;
            case OTHER:
            default:
                if (!fallbackToOther) {
                    log.warn("按其他下单类型计算预计收益，placeType={}，clerkId={}", placeType, clerkId);
                }
                estimatedRevenueVo.setRevenueAmount(baseAmount);
                estimatedRevenueVo.setRevenueRatio(100);
                break;
        }

        adjustRevenueByCoupon(clerkId, couponIds, estimatedRevenueVo);
        return estimatedRevenueVo;
    }

    private void fillRegularOrderRevenue(String clerkId, String firstOrder, BigDecimal orderAmount,
                                         PlayClerkLevelInfoEntity levelInfo, ClerkEstimatedRevenueVo vo) {
        if ("1".equals(firstOrder)) {
            int ratio = safeRatio(levelInfo.getFirstRegularRatio(), "firstRegularRatio", clerkId);
            vo.setRevenueRatio(ratio);
            vo.setRevenueAmount(scaleAmount(orderAmount, ratio));
        } else {
            int ratio = safeRatio(levelInfo.getNotFirstRegularRatio(), "notFirstRegularRatio", clerkId);
            vo.setRevenueRatio(ratio);
            vo.setRevenueAmount(scaleAmount(orderAmount, ratio));
        }
    }

    private void fillRandomOrderRevenue(String clerkId, String firstOrder, BigDecimal orderAmount,
                                        PlayClerkLevelInfoEntity levelInfo, ClerkEstimatedRevenueVo vo) {
        if ("1".equals(firstOrder)) {
            int ratio = safeRatio(levelInfo.getFirstRandomRadio(), "firstRandomRatio", clerkId);
            vo.setRevenueRatio(ratio);
            vo.setRevenueAmount(scaleAmount(orderAmount, ratio));
        } else {
            int ratio = safeRatio(levelInfo.getNotFirstRandomRadio(), "notFirstRandomRatio", clerkId);
            vo.setRevenueRatio(ratio);
            vo.setRevenueAmount(scaleAmount(orderAmount, ratio));
        }
    }

    private void fillRewardOrderRevenue(String clerkId, String firstOrder, BigDecimal orderAmount,
                                        PlayClerkLevelInfoEntity levelInfo, ClerkEstimatedRevenueVo vo) {
        if ("1".equals(firstOrder)) {
            int ratio = safeRatio(levelInfo.getFirstRewardRatio(), "firstRewardRatio", clerkId);
            vo.setRevenueRatio(ratio);
            vo.setRevenueAmount(scaleAmount(orderAmount, ratio));
        } else {
            int ratio = safeRatio(levelInfo.getNotFirstRewardRatio(), "notFirstRewardRatio", clerkId);
            vo.setRevenueRatio(ratio);
            vo.setRevenueAmount(scaleAmount(orderAmount, ratio));
        }
    }

    private int safeRatio(Integer ratio, String ratioField, String clerkId) {
        if (ratio == null) {
            log.warn("店员{}的等级配置字段{}缺失，已按0%处理", clerkId, ratioField);
            return 0;
        }
        return ratio;
    }

    private BigDecimal scaleAmount(BigDecimal baseAmount, int ratio) {
        return baseAmount
                .multiply(BigDecimal.valueOf(ratio).divide(new BigDecimal(100), 4, RoundingMode.HALF_UP))
                .setScale(2, RoundingMode.HALF_UP);
    }

    private void adjustRevenueByCoupon(String clerkId,
                                       List<String> couponIds,
                                       ClerkEstimatedRevenueVo estimatedRevenueVo) {
        List<String> safeCouponIds = couponIds == null ? Collections.emptyList() : couponIds;
        for (String couponId : safeCouponIds) {
            PlayCouponDetailsReturnVo couponInfo = playCouponDetailsService.selectPlayCouponDetailsById(couponId);
            if (couponInfo == null) {
                log.warn("优惠券信息不存在，couponId={}, clerkId={}", couponId, clerkId);
                continue;
            }
            if ("0".equals(couponInfo.getAttributionDiscounts())) {
                BigDecimal revenueAmount = estimatedRevenueVo.getRevenueAmount();
                if ("0".equals(couponInfo.getDiscountType())) {
                    revenueAmount = revenueAmount.subtract(couponInfo.getDiscountAmount());
                } else {
                    revenueAmount = revenueAmount.subtract(revenueAmount.subtract(couponInfo.getDiscountAmount()));
                }
                log.debug("优惠券ID={},优惠券类型={},优惠金额={},优惠前金额={},优惠后金额={}",
                        couponId,
                        couponInfo.getDiscountType(),
                        couponInfo.getDiscountAmount(),
                        estimatedRevenueVo.getRevenueAmount(),
                        revenueAmount);
                estimatedRevenueVo.setRevenueAmount(revenueAmount);
            }
        }
    }
}
