package cn.iocoder.yudao.module.iot.service.deviceattributetype;

import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceModelAttributeDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO;
import cn.iocoder.yudao.module.iot.dal.mysql.devicecontactmodel.DeviceContactModelMapper;
import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelattribute.DeviceModelAttributeMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.yudao.module.iot.controller.admin.deviceattributetype.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttributeTypeMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;

/**
 * 采集点分类 Service 实现类
 *
 * @author 内蒙必硕
 */
@Service
@Validated
public class DeviceAttributeTypeServiceImpl implements DeviceAttributeTypeService {

    @Resource
    private DeviceAttributeTypeMapper deviceAttributeTypeMapper;

    @Resource
    private DeviceModelAttributeMapper deviceModelAttributeMapper;

    @Resource
    private DeviceContactModelMapper deviceContactModelMapper;

    @Override
    public Long createDeviceAttributeType(DeviceAttributeTypeSaveReqVO createReqVO) {
        // 重复判断
        Long count = deviceAttributeTypeMapper.selectCount(new LambdaQueryWrapper<DeviceAttributeTypeDO>()
                .eq(DeviceAttributeTypeDO::getCode, createReqVO.getCode())
        );

        if (count > 0) {
            throw exception(DEVICE_CODE_EXISTS);
        }
        // 插入
        DeviceAttributeTypeDO deviceAttributeType = BeanUtils.toBean(createReqVO, DeviceAttributeTypeDO.class);
        deviceAttributeTypeMapper.insert(deviceAttributeType);
        // 返回
        return deviceAttributeType.getId();
    }

    @Override
    public void updateDeviceAttributeType(DeviceAttributeTypeSaveReqVO updateReqVO) {

        // 重复判断
        Long count = deviceAttributeTypeMapper.selectCount(new LambdaQueryWrapper<DeviceAttributeTypeDO>()
                .eq(DeviceAttributeTypeDO::getCode, updateReqVO.getCode())
                .ne(DeviceAttributeTypeDO::getId, updateReqVO.getId())
        );

        if (count > 0) {
            throw exception(DEVICE_CODE_EXISTS);
        }

        DeviceAttributeTypeDO deviceAttributeTypeDO = deviceAttributeTypeMapper.selectById(updateReqVO.getId());
        // 校验存在
        validateDeviceAttributeTypeExists(deviceAttributeTypeDO);
        // 更新
        DeviceAttributeTypeDO updateObj = BeanUtils.toBean(updateReqVO, DeviceAttributeTypeDO.class);
        deviceAttributeTypeMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDeviceAttributeType(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }

        // 批量校验存在性
        List<DeviceAttributeTypeDO> existList = deviceAttributeTypeMapper.selectBatchIds(ids);
        if (existList.size() != ids.size()) {
            throw exception(DEVICE_ATTRIBUTE_TYPE_NOT_EXISTS);
        }

        // 批量校验引用
        validateBatchReferences(ids);

        // 批量删除
        deviceAttributeTypeMapper.deleteByIds(ids);
    }

    private void validateBatchReferences(List<Long> ids) {
        // 批量查询引用
        boolean hasModelRef = deviceModelAttributeMapper.exists(
                Wrappers.<DeviceModelAttributeDO>lambdaQuery()
                        .in(DeviceModelAttributeDO::getAttributeType, ids));

        boolean hasContactRef = deviceContactModelMapper.exists(
                Wrappers.<DeviceContactModelDO>lambdaQuery()
                        .in(DeviceContactModelDO::getAttributeType, ids));

        if (hasModelRef || hasContactRef) {
            throw exception(DEVICE_ATTRIBUTE_TYPE_REFERENCES_EXISTS);
        }
    }

    private void validateDeviceAttributeTypeExists(DeviceAttributeTypeDO deviceAttributeTypeDO) {
        if (deviceAttributeTypeDO == null) {
            throw exception(DEVICE_ATTRIBUTE_TYPE_NOT_EXISTS);
        }
    }

    @Override
    public DeviceAttributeTypeDO getDeviceAttributeType(Long id) {
        return deviceAttributeTypeMapper.selectById(id);
    }

    @Override
    public PageResult<DeviceAttributeTypeDO> getDeviceAttributeTypePage(DeviceAttributeTypePageReqVO pageReqVO) {
        return deviceAttributeTypeMapper.selectPage(pageReqVO);
    }


    @Override
    public List<DeviceAttributeTypeDO> getDeviceAttributeTypeList() {
        return deviceAttributeTypeMapper.selectList();
    }

}