package com.ruoyi.system.task;

import com.ruoyi.common.constant.ServiceConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.YPMsgUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.ss.clean.domain.Clean;
import com.ruoyi.ss.clean.service.ICleanService;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.order.domain.Order;
import com.ruoyi.ss.order.domain.OrderVO;
import com.ruoyi.ss.order.service.IOrderService;
import com.ruoyi.ss.pay.service.IWxPayService;
import com.ruoyi.ss.room.domain.Room;
import com.ruoyi.ss.room.service.IRoomService;
import com.ruoyi.ss.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

import static com.ruoyi.common.constant.ServiceConstants.IS_REFUND_STATUS_REFUNDED;

/**
 * 定时任务调度测试
 *
 * @author ruoyi
 */
@Slf4j
@Component("ssTask")
public class SsTask {


    @Resource
    private IOrderService orderService;

    @Autowired
    private ICleanService cleanService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IRoomService roomService;

    @Resource
    private IWxPayService wxPayService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private DeviceService smDeviceService;



    /**
     * 1.启动时判断是否有未取消预约的订单
     * 2.判断已完成的订单未退还押金的
     * 3.启动时判断是否分账
     */
    @Transactional
    @PostConstruct
    public void init() {
    }

    /**
     *  结束订单处理
     *  查询未结束已到期的订单，通知保洁，修改订单状态
     */
    public void orderEndHandler(){
        log.info("-------------------【定时任务】结束订单处理---开始----------------");
        List<OrderVO> orderVOS = orderService.selectEndOrderList();
        for (OrderVO orderVO: orderVOS) {
            if(!orderVO.getIsSendMsg()){//没有通知过去通知保洁。修改订单状态：已结束、通知状态：已通知
                orderVO.setIsSendMsg(true);
                // todo 通知保洁, 发送短信  店铺id,保洁
                String merchantPhone = orderVO.getMerchantPhone();
                YPMsgUtils.sendClearMsg(orderVO.getRoomName(),merchantPhone);

                Clean clean = cleanService.buildClean(orderVO);
                int i = cleanService.insertEClean(clean);
                ServiceUtil.assertion(i==0,"生成保洁订单失败");
            }
            updateOrderStatus(orderVO,ServiceConstants.ORDER_STATUS_COMPLETED);
            // todo 改变房间状态，改为未打扫
            updateRoomStatus(orderVO,ServiceConstants.ROOM_STATUS_UNCLEANED);
        }
        log.info("-------------------【定时任务】结束订单处理---结束----------------");
    }

    /**
     *  开始使用处理
     *  查询待使用的订单，判断是否超过当前时间，
     *      如果超过当前时间修改订单状态：使用中
     *          房间也更新状态为使用中
     *      如果未超过当前时间则不修改
     */
    public void orderStartHandler(){
        log.info("-------------------【定时任务】开始使用处理---开始----------------");
        List<OrderVO> orderVOS = orderService.selectToeUsedOrderList();
        for (OrderVO orderVO: orderVOS) {
            if(orderVO.getReserveStartTime().before(DateUtils.getNowDate()) && orderVO.getReserveEndTime().after(DateUtils.getNowDate())){
                Boolean execute = transactionTemplate.execute(e -> {
                    // 订单中的预定开始时间 是否已超过当前时间
                    updateOrderStatus(orderVO,ServiceConstants.ORDER_STATUS_IN_USE);
                    // 改变房间状态，改为使用中
                    updateRoomStatus(orderVO,ServiceConstants.ROOM_STATUS_INUSE);

                    // 发送一次房间的全开  用time  门打开 其他的用settime
                    smDeviceService.roomAllDeviceSetTime(orderVO, "下单成功后房间全开");
                    return Boolean.TRUE;
                });
            }
        }
        log.info("-------------------【定时任务】开始使用处理---结束----------------");
    }

    /**
     *  押金自动退还处理 30秒执行一次
     *  查询所有智能押金模式下，还未退款的订单，根据实际退款时间退款
     */
    public void depositAutoRefund(){
        log.info("-------------------【定时任务】押金自动退还处理---开始----------------");
        List<OrderVO> orderVOS = orderService.selectNotRefundedOrderList();
        for (OrderVO orderVO: orderVOS) {
            // todo 是否加锁？判空
            // todo 更新订单是否退款状态
            Order order = new Order();
            order.setIsRefund(IS_REFUND_STATUS_REFUNDED);
            order.setOrderNo(orderVO.getOrderNo());
            int i = orderService.updateRlOrderByOrderNo(orderVO);
            ServiceUtil.assertion(i==0,"更新订单是否退款状态失败");

            String refNo = IdUtils.getOrderNo("ref");
            BigDecimal depositRefund = orderVO.getDepositRefund();
            wxPayService.refund(orderVO,"订单结束，已使用金额："+orderVO.getPayFee()+",退还剩余金额："+depositRefund, depositRefund,refNo,orderVO.getPayNo());
        }
        log.info("-------------------【定时任务】押金自动退还处理---结束----------------");
    }



    private void updateRoomStatus(OrderVO orderVO,String status) {
        Room room = new Room();
        room.setRoomId(orderVO.getRoomId());
        room.setStatus(status);
        int i = roomService.updateERoom(room);
        ServiceUtil.assertion(i==0,"更新房间状态失败");
    }

    private void updateOrderStatus(OrderVO orderVO,String status) {
        orderVO.setStatus(status);
        int i = orderService.updateRlOrderByOrderNo(orderVO);
        ServiceUtil.assertion(i==0,"更新订单状态失败");
    }

}
