package com.iformall.schedule;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iformall.domain.dto.WxSharingOrderDto;
import com.iformall.domain.po.*;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.service.WxOrderService;
import com.iformall.service.WxProfitSharingOrderService;
import com.iformall.service.WxRefundOrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Component
public class CouponOrderExpiringSchedule {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private WxCouponOrderMapper wxCouponOrderMapper;

    @Autowired
    private WxRefundOrderService wxRefundOrderService;

    @Autowired
    private WxProfitSharingOrderService wxProfitSharingOrderService;

    @Autowired
    private WxAppinfoMapper wxAppinfoMapper;

    @Autowired
    private WxPayOrderMapper wxPayOrderMapper;

    @Autowired
    private WxOrderMapper wxOrderMapper;

    @Autowired
    private WxOrderService wxOrderService;

    @Scheduled(cron = "0 5 0 * * ?") // 每天凌晨00:05
    // @Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次
    public void couponOrderExpiringSchedule() {

        List<WxCouponOrder> list = wxCouponOrderMapper.findExpiredFreeCouponOrderByValidDate();
        list.stream().forEach(co -> {
            // 券过期，更改状态及库存退回
            try {
                couponOrderExpire(co, true);
            } catch (Exception e) {
                logger.error(e.getMessage());
            }

        });

    }

    @Scheduled(cron = "0 5 0 * * ?") // 每天凌晨00:05
    // @Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次
    public void couponOrderRefundSchedule() {

        List<WxCouponOrder> list =  wxCouponOrderMapper.findExpiredCouponOrderByValidDate();

        list.stream().forEach(co -> {
            // 券过期，更改状态及库存退回
            try {
                couponOrderExpire(co, false);
            } catch (Exception e) {
                logger.error(e.getMessage());
            }

            // 退款
            try {
                couponOrderExpireRefund(co, true);
            } catch (Exception e) {
                logger.error(e.getMessage());
            }

        });
    }



    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void couponOrderExpire(WxCouponOrder co, boolean bStockBack) {
        // 标记 couponOrder过期
        WxCouponOrder updateRecord = new WxCouponOrder();
        updateRecord.setId(co.getId());
        if(co.getCouponType().equals(EnumCouponType.CARD_MULTIMCH.getCode())) {
            updateRecord.setCouponOrderStatus(EnumCouponOrderStatus.CARD_OVER_TIME.getCode()); // 卡线下退款
        } else {
            updateRecord.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_OVER_TIME.getCode()); //券已过期
        }
        updateRecord.setUpdateDate(new Date());
        wxCouponOrderMapper.updateById(updateRecord);

        // 库存退回
        if(bStockBack) {
            WxOrder order = wxOrderMapper.selectById(co.getOrderId());
            if(order != null) {
                wxOrderService.stockBack(order);
            }
        }
    }

    private void couponOrderExpireRefund(WxCouponOrder co, boolean bStockBack) {
        // 非储值卡, 可以退款
        if(!co.getCouponType().equals(EnumCouponType.CARD_MULTIMCH.getCode())
                && !co.getAutoRefund().equals(EnumCouponAutoRefund.UNSUPPORTED.getCode())) {
            WxAppinfo appinfo = new WxAppinfo();
            appinfo.setTenantId(co.getTenantId());
            appinfo.setType(EnumAppType.B.getCode());
            appinfo = wxAppinfoMapper.findList(appinfo).get(0);

            try {
                wxRefundOrderService.createRefundOrder(appinfo, co.getId(), EnumPayType.PAY_AUTO_REFUND, null);
            } catch (MallinkException e) {
                logger.error("退款失败:"+e.getMessage()+"couponOrderId="+co.getId());
                throw new MallinkException(e.getErrorCode(), e.getMessage());
            }
        }

        if (co.getAutoRefund().equals(EnumCouponAutoRefund.UNSUPPORTED.getCode())){
            // 不设退款，只能走微信分账-分账完结，把钱给分给商场
            try {
                WxPayOrder wxPayOrder = new WxPayOrder();
                wxPayOrder.setTenantId(co.getTenantId());
                wxPayOrder.setOrderId(co.getOrderId());
                wxPayOrder.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode());
                wxPayOrder = wxPayOrderMapper.selectOne(new QueryWrapper(wxPayOrder));
                if (wxPayOrder != null && wxPayOrder.getShare().equals(EnumPayShare.YES.getCode())) {
                    WxSharingOrderDto wxSharingOrderDto = new WxSharingOrderDto();
                    wxSharingOrderDto.setCUserId(wxPayOrder.getCUserId());
                    wxSharingOrderDto.setMerchantId(0L);
                    wxSharingOrderDto.setType(EnumProfitSharingOrderType.PROFIT_SHARING_SINGLE_FINISH.getCode());
                    wxSharingOrderDto.setPayAmount(wxPayOrder.getPayAmount());
                    wxSharingOrderDto.setOrderId(wxPayOrder.getId());
                    wxSharingOrderDto.setPayTimeStart(wxPayOrder.getPayTimeStart());
                    wxSharingOrderDto.setPayTimeEnd(wxPayOrder.getPayTimeEnd());
                    wxSharingOrderDto.setTenantId(wxPayOrder.getTenantId());
                    wxSharingOrderDto.setTransactionId(wxPayOrder.getTransactionId());
                    if (wxPayOrder.getRateAmount() != null) {
                        // 实际分账金额为 分账金额 + 通道费差
                        wxSharingOrderDto.setShareAmount(wxPayOrder.getShareAmount()+wxPayOrder.getRateAmount());
                    } else {
                        // 未设置通道费差
                        wxSharingOrderDto.setShareAmount(wxPayOrder.getShareAmount());
                    }
                    wxProfitSharingOrderService.finishSharingOrder(wxSharingOrderDto);
                }

            } catch (MallinkException e) {
                logger.error("券过期不退款: " + co.getId() + " ERROR:" + e.getMessage());
                throw new MallinkException(e.getErrorCode(), e.getMessage());
            }

            if(bStockBack) {
                // 库存退回
                WxOrder order = wxOrderMapper.selectById(co.getOrderId());
                if(order != null) {
                    wxOrderService.stockBack(order);
                }
            }
        }
    }
}