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

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceModelAttributeDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelrules.DeviceModelRulesDO;
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelattribute.DeviceModelAttributeMapper;
import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelrules.DeviceModelRulesMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.checkerframework.checker.units.qual.A;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.lang.invoke.LambdaConversionException;
import java.util.*;
import cn.iocoder.yudao.module.iot.controller.admin.devicemodel.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodel.DeviceModelDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.iot.dal.mysql.devicemodel.DeviceModelMapper;

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 DeviceModelServiceImpl implements DeviceModelService {

    @Resource
    private DeviceModelMapper deviceModelMapper;

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private DeviceModelAttributeMapper deviceModelAttributeMapper;

    @Resource
    private DeviceModelRulesMapper deviceModelRulesMapper;

    @Override
    public Long createDeviceModel(DeviceModelSaveReqVO createReqVO) {
        //编码重复判断
        Long count = deviceModelMapper.selectCount(new LambdaQueryWrapper<DeviceModelDO>()
                .eq(DeviceModelDO::getCode, createReqVO.getCode())
        );

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

        // 插入
        DeviceModelDO deviceModel = BeanUtils.toBean(createReqVO, DeviceModelDO.class);
        deviceModelMapper.insert(deviceModel);

        //插入点位规则
        insertionPointRule(deviceModel.getId());


        // 返回
        return deviceModel.getId();
    }

    private void insertionPointRule(Long id) {
        //TODO 待优化RUNNING及ALRAM
        List<DeviceModelRulesDO>  deviceModelRulesDOList = new ArrayList<>();

        DeviceModelRulesDO deviceModelRulesDO = new DeviceModelRulesDO();
        deviceModelRulesDO.setIdentifier("RUNNING");
        deviceModelRulesDO.setFieldName("运行");
        deviceModelRulesDO.setDefaultValue("运行");
        deviceModelRulesDO.setModelId(id);
        deviceModelRulesDOList.add(deviceModelRulesDO);
//
//        DeviceModelRulesDO deviceModelRulesDO1 = new DeviceModelRulesDO();
//        deviceModelRulesDO1.setIdentifier("ALARM");
//        deviceModelRulesDO1.setFieldName("报警");
//        deviceModelRulesDO1.setDefaultValue("报警");
//        deviceModelRulesDO1.setModelId(id);
//        deviceModelRulesDOList.add(deviceModelRulesDO1);

        deviceModelRulesMapper.insertBatch(deviceModelRulesDOList);

    }

    @Override
    public void updateDeviceModel(DeviceModelSaveReqVO updateReqVO) {
        //编码重复判断
        Long count = deviceModelMapper.selectCount(new LambdaQueryWrapper<DeviceModelDO>()
                .eq(DeviceModelDO::getCode, updateReqVO.getCode())
                .ne(DeviceModelDO::getId, updateReqVO.getId())

        );

        if (count > 0) {
            throw exception(DEVICE_MODEL_CODE_EXISTS);
        }
        // 校验存在
        validateDeviceModelExists(updateReqVO.getId());
        // 更新
        DeviceModelDO updateObj = BeanUtils.toBean(updateReqVO, DeviceModelDO.class);
        deviceModelMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDeviceModel(List<Long> idList ) {

        for (Long id : idList) {
            // 校验存在
            validateDeviceModelExists(id);
            //删除附属子表
            deleteModelAttribute(id);
        }
        // 删除
        deviceModelMapper.deleteByIds(idList);
    }

    private void deleteModelAttribute(Long id) {
        LambdaQueryWrapper<DeviceModelAttributeDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DeviceModelAttributeDO::getDeviceModelId,id);
        deviceModelAttributeMapper.delete(lambdaQueryWrapper);
    }

    private void validateDeviceModelExists(Long id) {
        if (deviceModelMapper.selectById(id) == null) {
            throw exception(DEVICE_MODEL_NOT_EXISTS);
        }
    }

    @Override
    public DeviceModelDO getDeviceModel(Long id) {
        return deviceModelMapper.selectById(id);
    }

    @Override
    public PageResult<DeviceModelDO> getDeviceModelPage(DeviceModelPageReqVO pageReqVO) {
        return deviceModelMapper.selectPage(pageReqVO);
    }

    @Override
    public List<DeviceModelDO> getDeviceModelList() {
        return deviceModelMapper.selectList(Wrappers.<DeviceModelDO>lambdaQuery().orderByDesc(DeviceModelDO::getCreateTime));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long copyDevice(Long id) {
        if (id == null){
            throw new RuntimeException("采集设备模型Id不能为空");
        }
        DeviceModelDO deviceModelDO = deviceModelMapper.selectById(id);
        if(deviceModelDO == null){
            throw new RuntimeException("该采集设备模型不存在！");
        }
        //复制实体类
        DeviceModelDO newDeviceMode = new DeviceModelDO();
        BeanUtils.copyProperties(deviceModelDO, newDeviceMode);
        newDeviceMode.setId(null);
        Random random = new Random();
        int randomNumber = random.nextInt(9000) + 1000;
        newDeviceMode.setCode(deviceModelDO.getCode()+ "-" + randomNumber);
        newDeviceMode.setName(deviceModelDO.getName() + "-副本");
        deviceModelMapper.insert(newDeviceMode);

        //复制关联表
        LambdaQueryWrapper<DeviceModelAttributeDO> lambdaConversionException = new LambdaQueryWrapper();
        lambdaConversionException.eq(DeviceModelAttributeDO::getDeviceModelId,deviceModelDO.getId());
        List<DeviceModelAttributeDO> deviceModelAttributeDOS = deviceModelAttributeMapper.selectList(lambdaConversionException);


        if (deviceModelAttributeDOS != null && !deviceModelAttributeDOS.isEmpty()){
            for (DeviceModelAttributeDO deviceModelAttributeDO : deviceModelAttributeDOS) {
                deviceModelAttributeDO.setId(null);
                deviceModelAttributeDO.setDeviceModelId(newDeviceMode.getId());
            }
            deviceModelAttributeMapper.insertBatch(deviceModelAttributeDOS);
        }

        return newDeviceMode.getId();
    }

}