package cn.iocoder.yudao.module.system.service.biz;

/**
 * @Author: jinyd
 * @CreateTime: 2024/8/19  11:42
 * @Description:
 * @Version: 4.0
 */


import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.DeviceModelDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ModelFieldDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.DeviceModelMapper;
import cn.iocoder.yudao.module.system.dal.mysql.biz.ModelFieldMapper;
import cn.iocoder.yudao.module.system.enums.device.DeviceModelTypeEnum;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.starter.annotation.LogRecord;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

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

@Service
@Validated
public class DeviceModelServiceImpl implements DeviceModelService {

    @Resource
    private DeviceModelMapper modelMapper;

    @Resource
    private ModelFieldMapper modelFieldMapper;

    @Override
    @LogRecord(type = DEVICE_MODEL_TYPE, subType = DEVICE_MODEL_CREATE_UPDATE_SUB_TYPE, bizNo = "{{#id}}",
            success = DEVICE_MODEL_CREATE_UPDATE_SUCCESS)
    public Long saveModel(DeviceModelSaveReqVO createReqVO) {
        // 插入
        DeviceModelDO model = BeanUtils.toBean(createReqVO, DeviceModelDO.class);
        if (model.getParentId() > 0) {
            model.setCombinationType(0);
        }
        if (null == createReqVO.getId()) {
            model.setModelValue(generateUniqueCode());
            modelMapper.insert(model);
            LogRecordContext.putVariable("operate", "创建");
        } else {
            modelMapper.updateById(model);
            LogRecordContext.putVariable("operate", "修改");
        }
        LogRecordContext.putVariable("id", model.getId());
        List<ModelFieldDO> modelFieldList = createReqVO.getModelFieldList();
        if (null != modelFieldList && modelFieldList.size() > 0) {
            modelFieldList.forEach(modelFieldDO -> {
                modelFieldDO.setDeviceModelId(model.getId());
                modelFieldDO.setModelType(model.getType());
                modelFieldDO.setTableName(DeviceModelTypeEnum.valueOf(modelFieldDO.getModelType()).getTableNmae());
                if (null != modelFieldDO.getId()) {
                    modelFieldMapper.updateById(modelFieldDO);
                } else {
                    modelFieldMapper.insert(modelFieldDO);
                }
            });
        }
        if (1 == createReqVO.getCombinationType() && null != createReqVO.getSubList() && createReqVO.getSubList().size() > 0) {
            List<DeviceModelSubRespVO> subList = createReqVO.getSubList();
            subList.forEach(deviceModelSubRespVO -> {
                List<ModelFieldDO> subModelFieldList = deviceModelSubRespVO.getModelFieldList();
                DeviceModelDO subModelDO = BeanUtils.toBean(deviceModelSubRespVO, DeviceModelDO.class);
                subModelDO.setParentId(model.getId());
                if (null == subModelDO.getId()) {
                    subModelDO.setModelValue(generateUniqueCode());
                    modelMapper.insert(subModelDO);
                } else {
                    modelMapper.updateById(subModelDO);
                }
                if (null != subModelFieldList && subModelFieldList.size() > 0) {
                    subModelFieldList.forEach(modelFieldDO -> {
                        modelFieldDO.setDeviceModelId(subModelDO.getId());
                        modelFieldDO.setModelType(subModelDO.getType());
                        modelFieldDO.setTableName(DeviceModelTypeEnum.valueOf(modelFieldDO.getModelType()).getTableNmae());
                        if (null != modelFieldDO.getId()) {
                            modelFieldMapper.updateById(modelFieldDO);
                        } else {
                            modelFieldMapper.insert(modelFieldDO);
                        }
                    });
                }
            });
        }

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

    public static String generateUniqueCode() {
        UUID uuid = UUID.randomUUID();
        long mostSigBits = uuid.getMostSignificantBits();
        long leastSigBits = uuid.getLeastSignificantBits();
        long combined = (mostSigBits ^ leastSigBits) & 0xFFFFFFFFFFFFL;
        return String.format("%018d", combined);
    }

    @Override
    public void updateModel(DeviceModelSaveReqVO updateReqVO) {
        // 校验存在
        validateModelExists(updateReqVO.getId());
        // 更新
        DeviceModelDO updateObj = BeanUtils.toBean(updateReqVO, DeviceModelDO.class);
        List<ModelFieldDO> modelFieldList = updateReqVO.getModelFieldList();
        if (null != modelFieldList && modelFieldList.size() > 0) {
            modelFieldList.forEach(modelFieldDO -> {
                modelFieldDO.setDeviceModelId(updateObj.getId());
                modelFieldDO.setModelType(updateObj.getType());
                modelFieldDO.setTableName(DeviceModelTypeEnum.valueOf(modelFieldDO.getModelType()).getTableNmae());
                if (null != modelFieldDO.getId()) {
                    modelFieldMapper.updateById(modelFieldDO);
                } else {
                    modelFieldMapper.insert(modelFieldDO);
                }
            });
        }
        updateObj.setCombinationType(0);
        modelMapper.updateById(updateObj);
    }

    @Override
    @LogRecord(type = DEVICE_MODEL_TYPE, subType = DEVICE_MODEL_DELETE_SUB_TYPE, bizNo = "{{#id}}",
            success = DEVICE_MODEL_DELETE_SUCCESS)
    public void deleteModel(Long id) {
        // 校验存在
        validateModelExists(id);
        // 删除
        modelMapper.deleteById(id);
    }

    private void validateModelExists(Long id) {
        DeviceModelDO deviceModelDO = modelMapper.selectById(id);
        if (deviceModelDO == null) {
            throw exception(DEVICE_MODEL_NOT_EXISTS);
        }
        LogRecordContext.putVariable("id", deviceModelDO.getId());
    }

    @Override
    @TenantIgnore
    public DeviceModelRespVO getModel(Long id) {
        DeviceModelDO deviceModelDO = modelMapper.selectById(id);
        if (deviceModelDO == null) {
            throw exception(DEVICE_MODEL_NOT_EXISTS);
        }

        DeviceModelRespVO deviceModelRespVO = BeanUtils.toBean(deviceModelDO, DeviceModelRespVO.class);
        List<ModelTableFieldVO> sleepReportList = modelFieldMapper.selectTableInfo(DeviceModelTypeEnum.valueOf(deviceModelDO.getType()).getTableNmae());
        Integer sort = 10;
        for (int i = 0; i < sleepReportList.size(); i++) {
            sleepReportList.get(i).setSort(sort);
            sort += 10;
        }
        if (deviceModelDO.getCombinationType() == 0) {
            deviceModelRespVO.setOriginalList(sleepReportList);
            deviceModelRespVO.setModelFieldList(modelFieldMapper.selectList(new LambdaQueryWrapperX<ModelFieldDO>()
                    .eq(ModelFieldDO::getDeviceModelId, id)));
            return deviceModelRespVO;
        }

        List<DeviceModelDO> deviceModelSubDOS = modelMapper.selectList(new LambdaQueryWrapperX<DeviceModelDO>()
                .eq(DeviceModelDO::getParentId, id).orderByDesc(DeviceModelDO::getId));
        if (null == deviceModelSubDOS || deviceModelSubDOS.size() < 1) {
            return deviceModelRespVO;
        }
        List<DeviceModelSubRespVO> subRespVOList = new ArrayList<>();
        deviceModelSubDOS.forEach(deviceModelSubDO -> {
            DeviceModelSubRespVO subRespVO = BeanUtils.toBean(deviceModelSubDO, DeviceModelSubRespVO.class);
            subRespVO.setOriginalList(sleepReportList);
            subRespVO.setModelFieldList(modelFieldMapper.selectList(new LambdaQueryWrapperX<ModelFieldDO>()
                    .eq(ModelFieldDO::getDeviceModelId, deviceModelSubDO.getId())));
            subRespVOList.add(subRespVO);
        });
        deviceModelRespVO.setSubList(subRespVOList);
        return deviceModelRespVO;
    }

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

    @Override
    public List<DeviceModelDO> getSubList(Long parentId) {
        return modelMapper.selectList(new LambdaQueryWrapperX<DeviceModelDO>()
                .eq(DeviceModelDO::getParentId,parentId).orderByDesc(DeviceModelDO::getId));
    }

    @Override
    public List<ModelFieldDO> getModelFielList(Long id) {
        return modelFieldMapper.selectList(new LambdaQueryWrapperX<ModelFieldDO>()
                .eq(ModelFieldDO::getDeviceModelId, id));
    }

    @Override
    @TenantIgnore
    public List<ModelTableFieldVO> getOriginalModelFielList(Integer type) {
        List<ModelTableFieldVO> sleepReportList = modelFieldMapper.selectTableInfo(DeviceModelTypeEnum.valueOf(type).getTableNmae());
        Integer sort = 10;
        for (int i = 0; i < sleepReportList.size(); i++) {
            sleepReportList.get(i).setSort(sort);
            sort += 10;
        }
        return sleepReportList;
    }

    @Override
    public DeviceModelCountVO getCount(Long deviceCategoryId) {
        Long count = modelMapper.selectCount(new LambdaQueryWrapperX<DeviceModelDO>()
                .eq(DeviceModelDO::getDeviceCategoryId, deviceCategoryId)
                .eq(DeviceModelDO::getParentId, 0l));
        Long enableCount = modelMapper.selectCount(new LambdaQueryWrapperX<DeviceModelDO>()
                .eq(DeviceModelDO::getDeviceCategoryId, deviceCategoryId)
                .eq(DeviceModelDO::getStatus, 1)
                .eq(DeviceModelDO::getParentId, 0l));
        Long disableCount = modelMapper.selectCount(new LambdaQueryWrapperX<DeviceModelDO>()
                .eq(DeviceModelDO::getDeviceCategoryId, deviceCategoryId)
                .eq(DeviceModelDO::getStatus, 0)
                .eq(DeviceModelDO::getParentId, 0l));
        return DeviceModelCountVO.builder().count(count).enableCount(enableCount).disableCount(disableCount).build();
    }

    @Override
    public List<ManufacturerModelRespVO> getManufacturerModelList() {
        return modelMapper.getManufacturerModelList();
    }
}
