package com.ruoyi.ss.room.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.constant.ServiceConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.equipment.domain.EquipmentVO;
import com.ruoyi.ss.equipment.service.IEquipmentService;
import com.ruoyi.ss.feeRule.domain.FeeRuleVO;
import com.ruoyi.ss.feeRule.service.IFeeRuleService;
import com.ruoyi.ss.feeRule.service.IFeeRuleValidator;
import com.ruoyi.ss.order.domain.OrderVO;
import com.ruoyi.ss.order.service.IOrderService;
import com.ruoyi.ss.room.domain.BandRuleDTO;
import com.ruoyi.ss.room.domain.Room;
import com.ruoyi.ss.room.domain.RoomQuery;
import com.ruoyi.ss.room.domain.RoomVO;
import com.ruoyi.ss.room.mapper.RoomMapper;
import com.ruoyi.ss.room.service.IRoomAssembler;
import com.ruoyi.ss.room.service.IRoomService;
import com.ruoyi.ss.room.service.IRoomValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import static com.ruoyi.common.constant.ServiceConstants.LOCK_CONDITION_CURRENT_ORDER;
import static com.ruoyi.common.constant.ServiceConstants.LOCK_CONDITION_HISTORICAL_ORDER;
import static com.ruoyi.common.utils.SecurityUtils.getUserId;

/**
 * 房间Service业务层处理
 *
 * @author qzz
 * @date 2024-11-20
 */
@Service
public class RoomValidatorImpl implements IRoomValidator
{
    @Autowired
    private RoomMapper eRoomMapper;

    @Autowired
    private DeviceService smDeviceService;

    @Autowired
    private IRoomAssembler roomAssembler;

    @Autowired
    private IRoomService roomService;

    @Autowired
    private IFeeRuleService feeRuleService;

    @Autowired
    private IFeeRuleValidator feeRuleValidator;

    @Autowired
    private IEquipmentService equipmentService;

    @Autowired
    private IOrderService orderService;

    /**
     * 开门前校验
     *
     * @param eRoomVO 房间对象
     * @return 房间
     */
    @Override
    public EquipmentVO preOpenDoor(RoomVO eRoomVO) {
        ServiceUtil.assertion(ObjectUtil.isNull(eRoomVO), "房间不存在");
        EquipmentVO door;
        if(ServiceConstants.ROOM_TYPE2_LOBBY_DEVICE.equals(eRoomVO.getType2())){
            door = equipmentService.selectDoorByRoomId(eRoomVO.getRoomId(), null);//如果是大厅设施，默认只有一个设施对象
        }else{
            door = equipmentService.selectDoorByRoomId(eRoomVO.getRoomId(), ServiceConstants.FACILITY_TYPE_ROOM_DOOR);
        }
        ServiceUtil.assertion(ObjectUtil.isNull(door), "房间门设施不存在");

        // todo 1. 如果是待使用的，可提前半小时开门，使用中的直接可以开门，其他情况都不能开
        // 有当前订单可进入  根据当前房间id判断是否有进行中的订单
        List<OrderVO> inProgressOrder = orderService.getInProgressOrderList(eRoomVO.getRoomId());
        ServiceUtil.assertion(inProgressOrder.isEmpty(), "当前无订单，不能开门，请先下单！");
        // 查找包含目标房间ID的订单
        Optional<OrderVO> roomOrderOptional = inProgressOrder.stream()
                .filter(orderVO -> orderVO.getRoomId().equals(eRoomVO.getRoomId()))
                .findFirst();
        // 断言该房间没有订单，请先下单（这个断言应该放在找到订单之后进行反向检查）
        ServiceUtil.assertion(!roomOrderOptional.isPresent(), "该房间没有订单，请先下单！");

        // 是否在预约时间范围内
        isInRangeTime(roomOrderOptional);
        return door;
    }

    private static void isInRangeTime(Optional<OrderVO> roomOrderOptional) {
        // 获取当前时间
        Date now = DateUtils.getNowDate();
        // 获取订单及其时间信息
        OrderVO roomOrder = roomOrderOptional.get();
        Date reserveStartTime = roomOrder.getReserveStartTime();
        Date reserveEndTime = roomOrder.getReserveEndTime();
        // 计算reserveStartTime往前推半个小时的时间
        Date timeAfterXMinutes = DateUtils.getTimeAfterXMinutes(reserveStartTime, -30);
        // 判断当前时间是否在[halfHourBeforeReserveStart, reserveEndTime]区间内
        boolean isValidTime = now.after(timeAfterXMinutes) && now.before(reserveEndTime);
        ServiceUtil.assertion(!isValidTime, "当前时间不在开锁预约时间范围内，请稍后再试！");
    }

    /**
     * 应用套餐前校验
     *
     * @param eRoomVO 房间对象
     * @return 房间
     */
    @Override
    public void preBandRule(BandRuleDTO eRoomVO) {
        // todo 1. 如果该房间已经存在小时套餐，做报错 2. 该套餐不是该商户的套餐，做报错  3. 该套餐不存在
        RoomVO roomVO = roomService.selectERoomByRoomId(eRoomVO.getRoomId());
        ServiceUtil.assertion(ObjectUtil.isNull(roomVO), "房间不存在");

        FeeRuleVO feeRuleVO = feeRuleService.selectEFeeRuleByRuleId(eRoomVO.getRuleId());
        ServiceUtil.assertion(ObjectUtil.isNull(feeRuleVO), "套餐不存在");

        // 校验基础套餐
        boolean rule = feeRuleValidator.isExistBasicsRule(roomVO.getRuleIds());
        ServiceUtil.assertion(rule, "该房间已经存在基础套餐");
    }
}
