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

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.constant.ServiceConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.equipment.domain.Equipment;
import com.ruoyi.ss.equipment.domain.EquipmentQuery;
import com.ruoyi.ss.equipment.domain.EquipmentVO;
import com.ruoyi.ss.equipment.service.IEquipmentService;
import com.ruoyi.ss.feeRule.service.IFeeRuleService;
import com.ruoyi.ss.room.domain.*;
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.store.domain.StoreVO;
import com.ruoyi.ss.store.service.IStoreService;
import com.ruoyi.ss.toilet.domain.ToiletVO;
import com.ruoyi.ss.wifi.domain.WifiVO;
import com.ruoyi.ss.wifi.service.IWifiService;
import org.apache.ibatis.annotations.Param;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

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

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

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private IStoreService storeService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private IEquipmentService equipmentService;

    @Autowired
    private IFeeRuleService feeRuleService;

    @Autowired
    private IWifiService wifiService;

    @Autowired
    private IRoomAssembler roomAssembler;


    /**
     * 查询房间
     *
     * @param roomId 房间主键
     * @return 房间
     */
    @Override
    public RoomVO selectERoomByRoomId(Long roomId)
    {
        return roomMapper.selectERoomByRoomId(roomId);
    }
//
//    /**
//     * 查询房间
//     *
//     * @param roomId 房间主键
//     * @return 房间
//     */
//    @Override
//    public RoomVO selectSimpleRoomByRoomId(Long roomId)
//    {
//        return roomMapper.selectERoomByRoomId(roomId);
//    }

    /**
     * 查询房间列表
     *
     * @param eRoom 房间
     * @return 房间
     */
    @Override
    public List<RoomVO> selectERoomList(RoomQuery eRoom)
    {
        return roomMapper.selectERoomList(eRoom);
    }

    /**
     * 查询房间ids
     *
     * @param query 条件
     * @return 房间集合
     */
    @Override
    public List<Long> selectRoomIdsList(RoomQuery query) {
        return roomMapper.selectRoomIdsList(query);
    }

    /**
     * 根据店铺id查询房间列表
     *
     * @param storeId 店铺id
     * @return 房间集合
     */
    @Override
    public List<RoomVO> selectERoomListByStoreId(Long storeId) {
        return roomMapper.selectERoomListByStoreId(storeId);
    }

    /**
     * 新增房间
     *
     * @param eRoom 房间
     * @return 结果  equipment
     */
    @Override
    public int insertERoom(Room eRoom)
    {
        if(StrUtil.isNotBlank(eRoom.getCode())){
            ServiceUtil.assertion(roomMapper.checkCodeIsExist(eRoom.getCode(), eRoom.getRoomId()), "房间码已存在,请重新生成");
        }
        eRoom.setCreateTime(DateUtils.getNowDate());
        Boolean execute = transactionTemplate.execute(e -> {
            String type = "";
            if(eRoom.getType2().equals(ROOM_TYPE2_LOBBY_DEVICE)){
                type = getType(eRoom.getEquType());
                eRoom.setType(type);
            }
            if(ObjectUtil.isNotNull(eRoom.getStoreId())){
                StoreVO storeVO = storeService.selectEStoreByStoreId(eRoom.getStoreId());
                ServiceUtil.assertion(storeVO == null, "店铺不存在");
                eRoom.setStoreName(storeVO.getName());
            }

            // 新增房间
            int i1 = roomMapper.insertERoom(eRoom);
            ServiceUtil.assertion(i1 == 0, "新增房间失败");

            // 新建房间时默认新建房间灯和房间门
            if(eRoom.getType2().equals(ROOM_TYPE2_PRIVATE_ROOM)){
                // 新建房间时默认新建房间灯和房间门
                int i2 = createEquipment(eRoom,"房间门",FACILITY_TYPE_ROOM_DOOR);
                ServiceUtil.assertion(i2 == 0, "新增房间门失败");

                int i3  = createEquipment(eRoom,"房间灯",FACILITY_TYPE_ROOM_LIGHT);
                ServiceUtil.assertion(i3 == 0, "新增房间灯失败");
            }else{
                int i4 = createEquipment(eRoom,eRoom.getRoomName(),type);
                ServiceUtil.assertion(i4 == 0, "新增设备失败");
            }

            // 店铺类型标签更新
            int i = storeService.updateStoreTypeTags(eRoom.getStoreId(), eRoom.getType());
            ServiceUtil.assertion(i == 0, "店铺类型标签更新失败");
            return Boolean.TRUE;
        });
        if(Boolean.FALSE.equals(execute))throw new ServiceException("新增房间失败");
        return 1;
    }

    private static @NotNull String getType(String equType) {
        String type = "";
        if(equType.equals(HALL_EQUIPMENT_TYPE_MAHJONG)){
            type = FACILITY_TYPE_MAHJONG_TABLE;
        }else if(equType.equals(HALL_EQUIPMENT_TYPE_BILLIARDS)){
            type = FACILITY_TYPE_BILLIARD_TABLE;
        }
        return type;
    }

    private int createEquipment(Room eRoom,String equipmentName,String type) {
        Equipment equipment = new Equipment();
        equipment.setRoomId(eRoom.getRoomId());
        equipment.setRoomName(eRoom.getRoomName());
        equipment.setName(equipmentName);
        equipment.setType(type);
        equipment.setStoreId(eRoom.getStoreId());
        equipment.setStoreName(eRoom.getStoreName());
        equipment.setMerchantId(eRoom.getMerchantId());
        return equipmentService.insertEquipment(equipment);
    }

    /**
     * 修改房间
     *
     * @param eRoom 房间
     * @return 结果
     */
    @Override
    public int updateERoom(Room eRoom)
    {
        Boolean execute = transactionTemplate.execute(e -> {
            String type = "";
            if(ROOM_TYPE2_LOBBY_DEVICE.equals(eRoom.getType2())){
                type = getType(eRoom.getEquType());
                eRoom.setType(type);
            }
            if(eRoom.getStoreId() != null && StrUtil.isNotBlank(eRoom.getType())){
                int i = storeService.updateStoreTypeTags(eRoom.getStoreId(), eRoom.getType());
                ServiceUtil.assertion(i == 0, "店铺类型标签更新失败");
            }

            int i = roomMapper.updateERoom(eRoom);
            ServiceUtil.assertion(i == 0, "修改房间失败");

            if(StrUtil.isNotBlank(eRoom.getRoomName())){// 同时更新设施中的房间名
                Equipment equipment = new Equipment();
                equipment.setRoomName(eRoom.getRoomName());
                equipment.setRoomId(eRoom.getRoomId());
                int i1 = equipmentService.updateEquipmentByRoomId(equipment);
                ServiceUtil.assertion(i1 == 0, "修改房间设施失败");
            }
            return Boolean.TRUE;
        });
        if(Boolean.FALSE.equals(execute))throw new ServiceException("【修改房间】失败");
        return 1;
    }

    @Override
    public int updateStoreName(Long storeId, String storeName) {
        Room eRoom = new Room();
        eRoom.setStoreId(storeId);
        eRoom.setStoreName(storeName);
        return roomMapper.updateStoreName(eRoom);
    }

    /**
     * 批量删除房间
     *
     * @param roomIds 需要删除的房间主键
     * @return 结果
     */
    @Override
    public int deleteERoomByRoomIds(Long[] roomIds)
    {
        // 关联删除房间下的设施
        equipmentService.deleteEquipmentByRoomId
                (roomIds);

        return roomMapper.deleteERoomByRoomIds(roomIds);
    }

    /**
     * 删除房间信息
     *
     * @param roomId 房间主键
     * @return 结果
     */
    @Override
    public int deleteERoomByRoomId(Long roomId)
    {
        return roomMapper.deleteERoomByRoomId(roomId);
    }

    /**
     * 开门
     * @param equipmentVO 房间对象
     */
    @Override
    public boolean openRoomDoor(EquipmentVO equipmentVO,boolean open, String reason, boolean returnMac) {
        return deviceService.controlDoor(equipmentVO.getDeviceId(),equipmentVO.getUnlockTime(),equipmentVO.getUnlockMode(),open, reason,true);
    }

    /**
     * 根据店铺查房间
     * @param storeId 店铺id
     * @return String
     */
    @Override
    public List<RoomVO> getRoomListByStoreId(Long storeId) {
        return selectERoomListByStoreId(storeId);
    }

    /**
     * 获取标签列表
     * @param storeId 店铺id
     * @return String
     */
    @Override
    public List<TagsVO> getTagListByStoreId(Long storeId) {
        return roomMapper.getTagListByStoreId(storeId);
    }

//    /**
//     * 下架设备
//     * @param deviceId 设备id
//     * @return String
//     */
//    @Override
//    public int offlineDevice(Long deviceId) {
//        return roomMapper.offlineDevice(deviceId);
//    }

    /**
     * 绑定房间门
     * @param dto 房间对象
     * @return String
     */
    @Override
    public int bandDoor(RoomDTO dto) {
        // 根据sn查询设备
        DeviceVO deviceVO = deviceService.selectBySn(dto.getSn());
        ServiceUtil.assertion(deviceVO == null, "设备不存在");
        // 更新房间门sn
        EquipmentVO equipmentVO = equipmentService.selectDoorByRoomId(dto.getRoomId(), FACILITY_TYPE_ROOM_DOOR);
        ServiceUtil.assertion(equipmentVO == null, "房间门设施不存在");

        EquipmentVO updateEquipment = new EquipmentVO();
        updateEquipment.setEquipmentId(equipmentVO.getEquipmentId());
        updateEquipment.setDeviceId(deviceVO.getDeviceId());
        return equipmentService.updateEquipment(updateEquipment);
    }

    /**
     * 添加大堂设备
     * @param room 房间对象
     * @return String
     */
    @Override
    public int addLobbyDevice(Room room) {
        return roomMapper.insertERoom(room);
    }


    /**
     * 应用套餐
     */
    @Override
    public int bandRule(BandRuleDTO dto) {
        RoomVO roomVO = roomMapper.selectERoomByRoomId(dto.getRoomId());
        ServiceUtil.assertion(roomVO == null,"房间不存在");

        Long ruleId = dto.getRuleId();
        List<Long> ruleIds = roomVO.getRuleIds();

        if(ruleIds.isEmpty()){
            ruleIds = new ArrayList<>();
        }

        // 检查是否已包含 deviceId，未包含则添加
        if (ruleIds.contains(ruleId)) {
            return 1;
        }

        List<Long> newDevices = new ArrayList<>(ruleIds);
        newDevices.add(ruleId);

        // 更新房间
        Room room = new Room();
        room.setRuleIds(newDevices);
        room.setRoomId(dto.getRoomId());
        int i = updateERoom(room);
        ServiceUtil.assertion(i == 0, "更新房间失败");
        return i;
    }

    /**
     * 批量应用套餐
     */
    @Override
    public int bandRules(BandRulesDTO dto) {
        RoomVO roomVO = roomMapper.selectERoomByRoomId(dto.getRoomId());
        ServiceUtil.assertion(roomVO == null,"房间不存在");
        // 更新房间
        Room room = new Room();
        room.setRuleIds(dto.getRuleIds());
        room.setRoomId(dto.getRoomId());
        int i = updateERoom(room);
        ServiceUtil.assertion(i == 0, "更新房间失败");
        return i;
    }

    /**
     * 解除套餐
     */
    @Override
    public int unBandRule(Long ruleId,Long roomId) {
        // todo 解绑前校验
        int i = roomMapper.unBandRule(ruleId,roomId);
        ServiceUtil.assertion(i ==0, "解除套餐失败");
        return i;
    }

    /**
     * 通过房间id查询所有设备id（除房间门外）
     */
    @Override
    public List<Long> selectAllDeviceIdsByRoomId(Long roomId) {
        return equipmentService.selectDeviceIdListByRoomId(roomId);
    }

    /**
     * 通过房间id查询所有设施id
     */
    @Override
    public List<Long> selectAllEquipmentIdsByRoomId(Long roomId) {
        return equipmentService.selectAllEquipmentIdsByRoomId(roomId);
    }

    @Override
    public List<Long> selectAllHallEquIdsByStoreId(Long storeId) {
        return equipmentService.selectAllHallEquIdsByStoreId(storeId);
    }

    /**
     * 获取空闲房间数
     */
    @Override
    public int selectIdleRoomNum(Long storeId) {
        return roomMapper.selectIdleRoomNum(storeId);
    }

    /**
     * 获取卫生间数
     */
    @Override
    public int selectToiletNum(Long storeId){
        return roomMapper.selectToiletNum(storeId);
    }

    /**
     * 套餐是否被应用
     */
    @Override
    public List<RoomVO> selectIsExistRule(Long ruleId) {
        return roomMapper.selectIsExistRule(ruleId);
    }

    /**
     * 配置房间wifi
     */
    @Override
    public int setWifi(SetWifiDTO dto) {
        WifiVO wifiVO = wifiService.selectWifiByWifiId(dto.getWifiId());
        ServiceUtil.assertion(wifiVO == null, "wifi不存在");
        Room room = new Room();
        room.setWifi(wifiVO.getWifi());
        room.setWifiPassword(wifiVO.getPassword());
        room.setRoomId(dto.getRoomId());
        return roomMapper.updateERoom(room);
    }

    /**
     * 获取wifi对象列表
     */
    @Override
    public List<WifiObjVO> selectWifiObjList() {
        RoomQuery query = new RoomQuery();
        query.setMerchantId(getUserId());
        List<RoomVO> roomVOS = roomMapper.selectERoomList(query);
        // 排除掉所有的卫生间,type2为3的是卫生间
        ArrayList<WifiObjVO> wifiObjVOS = new ArrayList<>();
        //把room转成wifiObjVOS，roomName对应name字段，roomId对应ObjId字段
        roomVOS.forEach(r -> {
            WifiObjVO wifiObjVO = new WifiObjVO();
            wifiObjVO.setName(r.getRoomName());
            wifiObjVO.setWifiName(r.getWifi());
            wifiObjVO.setObjId(r.getRoomId());
            wifiObjVOS.add(wifiObjVO);
        });
        return wifiObjVOS;
    }

    /**
     * 获取房间数
     */
    @Override
    public int getCount(RoomQuery query) {
        return roomMapper.getCount(query);
    }

    /**
     * code交换id
     */
    @Override
    public Long getId(String roomCode) {
        return roomMapper.getId(roomCode);
    }

    /**
     * 根据房间ids获取房间列表
     */
    @Override
    public List<RoomVO> selectERoomByRoomIds(List<Long> ids) {
        RoomQuery query = new RoomQuery();
        query.setRoomIds(ids);
        return selectERoomList(query);
    }

}
