package com.iformall.schedule;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.domain.po.WxOrder;
import com.iformall.enums.EnumAppType;
import com.iformall.enums.EnumOrderStatus;
import com.iformall.enums.EnumOrderType;
import com.iformall.enums.EnumRefundStatus;
import com.iformall.mapper.WxAppinfoMapper;
import com.iformall.mapper.WxCouponMapper;
import com.iformall.mapper.WxOrderGroupMapper;
import com.iformall.mapper.WxOrderMapper;
import com.iformall.service.WxOrderService;
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.HashMap;
import java.util.List;
import java.util.Map;

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

    private final int NORMAL_TIME_OUT = 15 * 60 * 1000; //普通券 必须15分钟内支付
    private final int PRESS_TIME_OUT  = 60 * 60 * 1000; //砍价券 必须60分钟内支付

    @Autowired
    WxOrderMapper wxOrderMapper;

    @Autowired
    WxOrderService wxOrderService;

    @Autowired
    WxOrderGroupMapper wxOrderGroupMapper;

    @Autowired
    WxAppinfoMapper wxAppinfoMapper;

    @Autowired
    WxRefundOrderService wxRefundOrderService;

    @Autowired
    WxCouponMapper wxCouponMapper;

    @Scheduled(cron = "0 */5 * * * *?") // 每5分钟检查一次
    //@Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次
    public void orderExpireSchedule() {

        Map dateMap = new HashMap();
        Date curDate = new Date();
        Date expireDate = new Date(curDate.getTime() - NORMAL_TIME_OUT );

        // 券相关订单, 15分钟未支付, 订单过期
        dateMap.put("type", EnumOrderType.COUPON.getCode());
        dateMap.put("endDate", expireDate);
        List<WxOrder> orderCoupons = wxOrderMapper.findListOfUnpaidOrderByDate(dateMap);
        orderCoupons.stream().forEach( o -> {
            try {
                orderExpired(o);
            } catch (Exception e) {
                logger.error("券过期失败" + e.getMessage());
            }
        });

        // 砍价相关订单,
        //    1. 如果已经砍价完成，必须60分钟内支付, 未支付，订单过期
        Date pressExpireDate = new Date(curDate.getTime() - PRESS_TIME_OUT );
        dateMap.put("type", EnumOrderType.COUPON.getCode());
        dateMap.put("endDate", pressExpireDate);
        List<WxOrder> orderPresss = wxOrderMapper.findListOfCompleteUnPaidPressOrderByDate(dateMap);
        orderPresss.stream().forEach( o -> {
            try {
                orderPressExpired(o, true);
            } catch (Exception e) {
                logger.error("砍价券支付过期失败" + e.getMessage());
            }
        });
        //    2. 当前已超过砍价结束时间, 订单过期
        dateMap.put("type", EnumOrderType.COUPON.getCode());
        dateMap.put("endDate", curDate);
        orderPresss = wxOrderMapper.findListOfUnpaidPressOrderByDate(dateMap);
        orderPresss.stream().forEach( o -> {
            try {
                orderPressExpired(o, false);
            } catch (Exception e) {
                logger.error("砍价券过期失败" +e.getMessage());
            }
        });


        // 拼团取消
        WxOrder order = new WxOrder();
        order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode());
        wxOrderMapper.selectList(new QueryWrapper(order)).stream().forEach(o -> {
            try {
                orderGroupExpired((WxOrder) o);
            } catch (Exception e) {
                logger.error("拼团取消失败" + e.getMessage());
            }
        });

        //更新拼团过期状态
        wxOrderMapper.updateOrderStatusForGroup();
        //拼团过期
        order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_OVERTIME.getCode());
        wxOrderMapper.selectList(new QueryWrapper(order)).stream().forEach(o -> {
            try {
                returnMoney((WxOrder) o);
            } catch (Exception e) {
                logger.error("拼团过期退款失败" + e.getMessage());
            }
        });


        //拼团券下架
        order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_CANCEL.getCode());
        wxOrderMapper.selectList(new QueryWrapper(order)).stream().forEach(o -> {
            try {
                returnMoney((WxOrder) o);
            } catch (Exception e) {
                logger.error("拼团券下架退款失败" + e.getMessage());
            }
        });

        //参团失败
        order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_FAILD.getCode());
        wxOrderMapper.selectList(new QueryWrapper(order)).stream().forEach(o -> {
            try {
                returnMoney((WxOrder) o);
            } catch (Exception e) {
                logger.error("参团失败退款失败" + e.getMessage());
            }
        });


    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void orderExpired(WxOrder order) {

        WxOrder updateOrder = new WxOrder();
        updateOrder.setId(order.getId());
        updateOrder.setUpdateDate(new Date());
        updateOrder.setOrderStatus(EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL.getCode());
        wxOrderMapper.updateById(updateOrder);

        // 库存退回
        wxOrderService.stockBack(order);

        // 微信 关单
        wxOrderService.orderClose(updateOrder);

        logger.info("券订单: " + order.getId() + " create at " + order.getCreateDate() + " expired at " + new Date());
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void orderPressExpired(WxOrder order, boolean payExpired) {
        Date curDate = new Date();
        WxOrder updateOrder = new WxOrder();
        updateOrder.setId(order.getId());
        updateOrder.setTenantId(order.getTenantId());
        updateOrder.setOrderStatus(EnumOrderStatus.ORDER_STATUS_PRESS_OVERTIME.getCode());
        updateOrder.setUpdateDate(curDate);
        wxOrderMapper.updateById(updateOrder);
        // 库存退回
        wxOrderService.stockBack(order);

        if(payExpired) {
            logger.info("砍价订单(支付过期): " + order.getId() + ", tenantId" + order.getTenantId() + " create at " + order.getCreateDate() +  ", update at " + order.getUpdateDate() + " expired at " + curDate);
        } else {
            logger.info("砍价订单(过期): " + order.getId() + ", tenantId" + order.getTenantId() + " create at " + order.getCreateDate() + " expired at " + curDate);
        }
    }


    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void orderGroupExpired(WxOrder order) {
        Date curDate = new Date();
        WxOrder updateOrder = new WxOrder();
        updateOrder.setId(order.getId());
        updateOrder.setTenantId(order.getTenantId());
        updateOrder.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_BREAK.getCode());
        updateOrder.setUpdateDate(curDate);
        wxOrderMapper.updateById(updateOrder);
        // 库存退回
        wxOrderService.stockBack(order);

        // 微信 关单
        wxOrderService.orderClose(updateOrder);
        logger.info("拼团订单: " + order.getId() + " create at " + order.getCreateDate() + " expired at " + curDate);
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void returnMoney(WxOrder order) {

        //获取APP信息
        WxAppinfo appinfo = new WxAppinfo();
        appinfo.setTenantId(order.getTenantId());
        appinfo.setType(EnumAppType.C.getCode());
        appinfo = wxAppinfoMapper.findList(appinfo).get(0);
        //退款流程
        boolean has = wxRefundOrderService.hasRefundOrder(order.getId(), EnumRefundStatus.REFUND_SUCCESS.getCode());
        if (!has) {
            wxRefundOrderService.returnMoney(appinfo, order.getId());
        }
    }

}