package cn.iocoder.yudao.module.member.job;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.member.dal.dataobject.card.CardDO;
import cn.iocoder.yudao.module.member.dal.dataobject.diningplates.DiningPlatesDO;
import cn.iocoder.yudao.module.member.dal.dataobject.order.DishOrderDO;
import cn.iocoder.yudao.module.member.enums.TimePeriodEnum;
import cn.iocoder.yudao.module.member.service.card.CardService;
import cn.iocoder.yudao.module.member.service.diningplates.DiningPlatesService;
import cn.iocoder.yudao.module.member.service.order.OrderService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 自动扣款 Job
 *
 * @author j-sentinel
 */
@Slf4j
@Component
public class BalanceDeductionJob implements JobHandler {

    @Resource
    private DiningPlatesService platesService;
    @Resource
    private OrderService orderService;
    @Resource
    private CardService cardService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private MemberUserService userService;

    /**
     * 30分钟之后自动解绑并扣款
     */
    private static final Integer EXPIRATION_TIME = 30;


    @Override
    @TenantIgnore
    @Transactional(rollbackFor = Exception.class)
    public String execute(String param) {
        //查询扣费用户
        List<DiningPlatesDO> diningPlatesToCharging = platesService.getDiningPlatesToCharging(EXPIRATION_TIME);
        int size = 0;

        if (CollectionUtil.isNotEmpty(diningPlatesToCharging)) {
            List<Long> ids = diningPlatesToCharging.stream().map(DiningPlatesDO::getId).collect(Collectors.toList());
            List<Long> orderIds = diningPlatesToCharging.stream().map(DiningPlatesDO::getOrderId).collect(Collectors.toList());
            //先更改状态防止重复消费
            //platesService.updatePayFlag(ids,DiningPlatesDO.PAY);
            //获取用户订单
            List<DishOrderDO> toPay = orderService.getToPayByOrder(orderIds);
            //扣除余额
            List<CardDO> list = new ArrayList<>();
            toPay.forEach(dishOrderDO -> {
                //新的总价
                String s = stringRedisTemplate.opsForValue().get(dishOrderDO.getDiningPlatesNum() + "-" + dishOrderDO.getStoreId());
                BigDecimal total = new BigDecimal(StrUtil.isBlank(s)?"0":s);
                //BigDecimal total = new BigDecimal(0.01);
                Long userId = dishOrderDO.getUserId();
                CardDO cardDO = new CardDO();
                cardDO.setType(TimePeriodEnum.getTimePeriod(LocalDateTime.now()));
                CardDO oldCardDO = cardService.getCardDoByUserId(userId);


                BigDecimal money = oldCardDO.getMoney();
                //计算减免价格
                BigDecimal reductionAmount = BigDecimal.ZERO;
                if (total.compareTo(BigDecimal.ZERO) > 0) {
                    reductionAmount = userService.getReductionAmount(userId, total, dishOrderDO.getCreateTime());
                }
                dishOrderDO.setReductionAmount(reductionAmount);
                dishOrderDO.setReductionState(reductionAmount.compareTo(BigDecimal.ZERO) > 0 ? "1" : "0");

                //计算减免后的总价
                if(total.compareTo(reductionAmount)<0){
                    total = BigDecimal.ZERO;
                }else {
                    total = total.subtract(reductionAmount);
                }
                
                BigDecimal wxAmount = oldCardDO.getWxAmount();
                BigDecimal giftAmount = oldCardDO.getGiftAmount();
                BigDecimal cashAmount = oldCardDO.getCashAmount();
                cardDO.setMoney(money.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP));
                //待支付金额 最大退款金额
                dishOrderDO.setRefundAmount(total);
                if (money.compareTo(BigDecimal.ZERO) <= 0) {
                    dishOrderDO.setPayAmount(total);
                    dishOrderDO.setRefundAmount(BigDecimal.ZERO);
                } else {
                    if (total.compareTo(money) > 0) {
                        dishOrderDO.setPayAmount(total.subtract(money).setScale(2, BigDecimal.ROUND_HALF_UP));
                        dishOrderDO.setRefundAmount(money);
                    }
                }

                if (total.compareTo(money) > 0) {
                    dishOrderDO.setOrderStatus(DishOrderDO.TOCOMPLETE);
                    dishOrderDO.setWxAmount(wxAmount);
                    dishOrderDO.setCashAmount(cashAmount);
                    dishOrderDO.setGiftAmount(giftAmount);
                } else {
                    dishOrderDO.setOrderStatus(DishOrderDO.COMPLETE);
                    //计算金额
                    if (total.compareTo(wxAmount) <= 0) {
                        cardDO.setWxAmount(wxAmount.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP));
                        dishOrderDO.setWxAmount(total);
                    } else {
                        cardDO.setWxAmount(BigDecimal.ZERO);
                        dishOrderDO.setWxAmount(wxAmount);
                        BigDecimal total1 = total.subtract(wxAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
                        if (total1.compareTo(cashAmount) <= 0) {
                            cardDO.setCashAmount(cashAmount.subtract(total1).setScale(2, BigDecimal.ROUND_HALF_UP));
                            dishOrderDO.setCashAmount(total1);
                        } else {
                            cardDO.setCashAmount(BigDecimal.ZERO);
                            dishOrderDO.setCashAmount(cashAmount);
                            BigDecimal total2 = total1.subtract(cashAmount).setScale(2, BigDecimal.ROUND_HALF_UP);

                            cardDO.setGiftAmount(giftAmount.subtract(total2).setScale(2, BigDecimal.ROUND_HALF_UP));
                            dishOrderDO.setGiftAmount(total2);
                        }
                    }

                }

                cardDO.setUserId(userId);
                cardDO.setChangeMoney(total);
                cardDO.setFlag(CardDO.MINUS);
                cardService.insertOne(cardDO);
                list.add(cardDO);

                dishOrderDO.setTotalMoney(total);
                dishOrderDO.setUpdateTime(LocalDateTime.now());
                stringRedisTemplate.delete(dishOrderDO.getDiningPlatesNum()+ "-" + dishOrderDO.getStoreId());
            });
            //取消批量，防止同一人订餐少扣款
            //cardService.insertBatch(list);
            size = list.size();
            //餐盘解绑
            platesService.updateBind(ids);
            //更新订单状态和总价
            orderService.updateBatch(toPay);
        }

        log.info("[execute][扣款定时任务扣款数量 ({}) 个]", size);
        return String.format("扣款定时任务扣款数量 %s 个", size);
    }

}
