package cn.hanghui.outapi.platform.tenant.service.impl;

import cn.hanghui.outapi.platform.common.entity.rest.RestCode;
import cn.hanghui.outapi.platform.common.utils.ClassUtil;
import cn.hanghui.outapi.platform.common.utils.Preconditions;
import cn.hanghui.outapi.platform.tenant.entity.config.device.template.DeviceTemplateDto;
import cn.hanghui.outapi.platform.tenant.entity.config.device.template.DeviceTemplateLessVo;
import cn.hanghui.outapi.platform.tenant.entity.config.device.template.DeviceTemplateSearch;
import cn.hanghui.outapi.platform.tenant.entity.config.device.template.DeviceTemplateVo;
import cn.hanghui.outapi.platform.tenant.entity.dto.DeviceDefaultParam;
import cn.hanghui.outapi.platform.tenant.entity.enums.*;
import cn.hanghui.outapi.platform.tenant.entity.po.*;
import cn.hanghui.outapi.platform.tenant.mapper.*;
import cn.hanghui.outapi.platform.tenant.service.DeviceTemplateService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 设备 服务实现类
 * </p>
 *
 * @author wxg
 * @since 2023-12-29
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DeviceTemplateServiceImpl implements DeviceTemplateService {
    private final DeviceTemplateMapper deviceTemplateMapper;
    private final ApplicationTypeMapper applicationTypeMapper;
    private final DeviceModelMapper deviceModelMapper;
    private final AmpeMapper ampeMapper;
    private final TenantMapper tenantMapper;
    private final UserLibMapper userLibMapper;
    private final SceneMapper sceneMapper;
    private final CommonImpl commonImpl;

    @Override
    public Boolean edit(DeviceTemplateDto dto) {
        this.checkDto(dto);
        Long deviceTemplateId = dto.getDeviceTemplateId();
        if (deviceTemplateId == null) {
            DeviceTemplate deviceTemplate = BeanUtil.copyProperties(dto, DeviceTemplate.class);
            deviceTemplateMapper.insert(deviceTemplate);
        } else {
            DeviceTemplate base = deviceTemplateMapper.selectById(deviceTemplateId);
            ClassUtil.throwBusinessException(ObjectUtil.isNull(base), "设备模版不存在");
            BeanUtil.copyProperties(dto, base);
            deviceTemplateMapper.updateById(base);
        }
        return true;
    }

    private void checkDto(DeviceTemplateDto dto) {
        //应用类型
        if (Preconditions.isNotBlank(dto.getApplicationTypeId())) {
            ApplicationType applicationType = applicationTypeMapper.selectById(dto.getApplicationTypeId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(applicationType), "应用类型不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(applicationType.getIsDeleted()), "购买方已删除");
        }
        //设备类型（硬件）
        if (Preconditions.isNotBlank(dto.getDeviceModelHardwareId())) {
            DeviceModel deviceModelHardware = deviceModelMapper.selectById(dto.getDeviceModelHardwareId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelHardware), "设备类型（硬件）不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelHardware.getIsDeleted()), "设备类型（硬件）已删除");
        }
        //设备类型（环境）
        if (Preconditions.isNotBlank(dto.getDeviceModelEnvironmentId())) {
            DeviceModel deviceModelEnvironment = deviceModelMapper.selectById(dto.getDeviceModelEnvironmentId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelEnvironment), "设备类型（环境）不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelEnvironment.getIsDeleted()), "设备类型（环境）已删除");
        }
        //服务商平台
        if (ObjectUtil.isNotNull(dto.getTenantId())) {
            Tenant tenant = tenantMapper.selectById(dto.getTenantId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(tenant), "服务商平台不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(tenant.getIsDeleted()), "服务商平台已删除");
        }
        //用户库
        if (ObjectUtil.isNotNull(dto.getUserLibId())) {
            UserLib userLib = userLibMapper.selectById(dto.getUserLibId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(userLib), "用户库不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(userLib.getIsDeleted()), "用户库已删除");
        }
        //场景
        if (ObjectUtil.isNotNull(dto.getSceneId())) {
            Scene scene = sceneMapper.selectById(dto.getSceneId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(scene), "场景不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(scene.getIsDeleted()), "场景已删除");
        }
        //模式
        if (ObjectUtil.isNotNull(dto.getMode())) {
            ModeEnum modeEnum = ModeEnum.getEnumByCode(dto.getMode());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(modeEnum), "模式不存在");
        }
        //系统类型
        if (Preconditions.isNotBlank(dto.getSystemTypeCode())) {
            SystemTypeEnum systemTypeEnum = SystemTypeEnum.getEnumByCode(dto.getSystemTypeCode());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(systemTypeEnum), "系统类型不存在");
        }
        //摄像头类型
        if (Preconditions.isNotBlank(dto.getCameraType())) {
            CameraTypeEnum cameraTypeEnum = CameraTypeEnum.getEnumByCode(dto.getCameraType());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(cameraTypeEnum), "摄像头类型不存在");
        }
        //摄像头品牌
        if (Preconditions.isNotBlank(dto.getCameraBrand())) {
            CameraBrandEnum cameraBrandEnum = CameraBrandEnum.getEnumByCode(dto.getCameraBrand());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(cameraBrandEnum), "摄像品牌不存在");
        }
        //进场刷脸模式
        if (Preconditions.isNotBlank(dto.getEntryFaceMode())) {
            EntryFaceModeEnum entryFaceModeEnum = EntryFaceModeEnum.getEnumByCode(dto.getEntryFaceMode());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(entryFaceModeEnum), "进场刷脸模式不存在");
        }
        //用户信息输出模式
        if (Preconditions.isNotBlank(dto.getUserOutputMode())) {
            UserOutputModeEnum userOutputModeEnum = UserOutputModeEnum.getEnumByCode(dto.getUserOutputMode());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(userOutputModeEnum), "用户信息输出模式不存在");
        }
        //身份证阅读器品牌
        if (Preconditions.isNotBlank(dto.getIdCardReaderBrand())) {
            IdCardReaderBrandEnum idCardReaderBrandEnum = IdCardReaderBrandEnum.queryEnumByCode(dto.getIdCardReaderBrand());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(idCardReaderBrandEnum), RestCode.FAIL.getCode(), "身份证阅读器品牌不存在");
        }
//        //联动平台校验模式
//        if(!dto.getUseLinkage()){//没有开启联动平台，赋默认值
//            dto.setLinkageCheckMode(DeviceDefaultParam.defaultLinkageCheckMode);
//        }
        if (Preconditions.isNotBlank(dto.getLinkageCheckMode())) {
            LinkageCheckModeEnum linkageCheckModeEnum = LinkageCheckModeEnum.getEnumByCode(dto.getLinkageCheckMode());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(linkageCheckModeEnum), RestCode.FAIL.getCode(), "联动平台校验模式不存在");
        }
        //结果页模版
        if (Preconditions.isNotBlank(dto.getResultPageTemplate())) {
            ResultPageTemplateEnum resultPageTemplateEnum = ResultPageTemplateEnum.getEnumByCode(dto.getResultPageTemplate());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(resultPageTemplateEnum), RestCode.FAIL.getCode(), "结果页模版不存在");
        }
        //继电器开门模式
        if (ObjectUtil.isNotNull(dto.getRelayOpenModel())) {
            RelayOpenModelEnum relayOpenModelEnum = RelayOpenModelEnum.getEnumByCode(dto.getRelayOpenModel());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(relayOpenModelEnum), "继电器开门模式不存在");
            if(RelayOpenModelEnum.OPEN_CLOSE.getCode().equals(dto.getRelayOpenModel())){
                ClassUtil.throwBusinessException(dto.getOpenCloseInterval() == null, "继电器开门模式选择开-闭信号，请填写开闭时间间隔（s）");
                ClassUtil.throwBusinessException(dto.getSignalInterval() == null, "继电器开门模式选择开-闭信号，请填写信号间间隔（s）");
            }else if(RelayOpenModelEnum.OPEN_GATE_CLOSE.getCode().equals(dto.getRelayOpenModel())){
                ClassUtil.throwBusinessException(dto.getGateTimeOut() == null, "继电器开门模式选择开-门磁-闭信息，门磁超时时间（s）");
            }
        }
    }

    @Override
    public List<DeviceTemplateLessVo> deviceTemplateList() {
        LambdaQueryWrapper<DeviceTemplate> wrapper = new LambdaQueryWrapper<>();
        //查询的基础条件
        wrapper.eq(DeviceTemplate::getIsDeleted, Boolean.FALSE);
        wrapper.orderByDesc(DeviceTemplate::getId);
        List<DeviceTemplate> deviceTemplateList = deviceTemplateMapper.selectList(wrapper);

        return deviceTemplateList.stream().map(p -> new DeviceTemplateLessVo()
                .setDeviceTemplateId(p.getId())
                .setTemplateName(p.getTemplateName())).collect(Collectors.toList());
    }

    @Override
    public IPage<DeviceTemplateVo> deviceTemplatePage(DeviceTemplateSearch dto) {
        Page<DeviceTemplate> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        LambdaQueryWrapper<DeviceTemplate> wrapper = this.getWrapper(dto);
        IPage<DeviceTemplate> iPage = deviceTemplateMapper.selectPage(page, wrapper);

        Map<Long, ApplicationType> applicationTypeMap = commonImpl.getApplicationTypeMap(iPage, DeviceTemplate::getApplicationTypeId);
        Map<Long, DeviceModel> deviceModelHardwareMap = commonImpl.getDeviceModelMap(iPage, DeviceTemplate::getDeviceModelHardwareId);
        Map<Long, DeviceModel> deviceModelEnvironmentMap = commonImpl.getDeviceModelMap(iPage, DeviceTemplate::getDeviceModelEnvironmentId);
        Map<Long, Tenant> tenantMap = commonImpl.getTenantMap(iPage, DeviceTemplate::getTenantId);
        Map<Long, UserLib> userLibMap = commonImpl.getUserLibMap(iPage, DeviceTemplate::getUserLibId);
        Map<Long, Scene> sceneMap = commonImpl.getSceneMap(iPage, DeviceTemplate::getSceneId);

        return iPage.convert(t -> {
            DeviceTemplateVo item = BeanUtil.copyProperties(t, DeviceTemplateVo.class);

            item.setDeviceTemplateId(t.getId());
            if (applicationTypeMap.containsKey(t.getApplicationTypeId())) {
                item.setApplicationType(applicationTypeMap.get(t.getApplicationTypeId()).getApplicationType());
            }
            if (deviceModelHardwareMap.containsKey(t.getDeviceModelHardwareId())) {
                item.setDeviceModelHardware(deviceModelHardwareMap.get(t.getDeviceModelHardwareId()).getDeviceModel());
            }
            if (deviceModelEnvironmentMap.containsKey(t.getDeviceModelEnvironmentId())) {
                item.setDeviceModelEnvironment(deviceModelEnvironmentMap.get(t.getDeviceModelEnvironmentId()).getDeviceModel());
            }
            if (tenantMap.containsKey(t.getTenantId())) {
                item.setTenantName(tenantMap.get(t.getTenantId()).getName());
            }
            if (userLibMap.containsKey(t.getUserLibId())) {
                item.setUserLibName(userLibMap.get(t.getUserLibId()).getUserLibName());
            }
            if (sceneMap.containsKey(t.getSceneId())) {
                item.setSceneName(sceneMap.get(t.getSceneId()).getSceneName());
            }
            SystemTypeEnum systemTypeEnum = SystemTypeEnum.getEnumByCode(t.getSystemTypeCode());
            if (ObjectUtil.isNotNull(systemTypeEnum)) {
                item.setSystemType(systemTypeEnum.getDesc());
            }

            return item;
        });
    }

    private LambdaQueryWrapper<DeviceTemplate> getWrapper(DeviceTemplateSearch dto) {
        LambdaQueryWrapper<DeviceTemplate> wrapper = new LambdaQueryWrapper<>();
        //查询的传参条件
        wrapper.eq(ObjectUtil.isNotNull(dto.getDeviceTemplateId()), DeviceTemplate::getId, dto.getDeviceTemplateId());
        wrapper.eq(ObjectUtil.isNotNull(dto.getApplicationTypeId()), DeviceTemplate::getApplicationTypeId, dto.getApplicationTypeId());
        wrapper.eq(ObjectUtil.isNotNull(dto.getDeviceModelHardwareId()), DeviceTemplate::getDeviceModelHardwareId, dto.getDeviceModelHardwareId());
        wrapper.eq(ObjectUtil.isNotNull(dto.getDeviceModelEnvironmentId()), DeviceTemplate::getDeviceModelEnvironmentId, dto.getDeviceModelEnvironmentId());
        wrapper.eq(ObjectUtil.isNotNull(dto.getSystemTypeCode()), DeviceTemplate::getSystemTypeCode, dto.getSystemTypeCode());
        wrapper.eq(ObjectUtil.isNotNull(dto.getTenantId()), DeviceTemplate::getTenantId, dto.getTenantId());
        wrapper.eq(ObjectUtil.isNotNull(dto.getUserLibId()), DeviceTemplate::getUserLibId, dto.getUserLibId());
        wrapper.eq(ObjectUtil.isNotNull(dto.getSceneId()), DeviceTemplate::getSceneId, dto.getSceneId());
        wrapper.eq(ObjectUtil.isNotNull(dto.getMode()), DeviceTemplate::getMode, dto.getMode());
        //查询的基础条件
        wrapper.eq(DeviceTemplate::getIsDeleted, Boolean.FALSE);
        wrapper.orderByDesc(DeviceTemplate::getId);
        return wrapper;
    }

    @Override
    public Boolean deviceTemplateDelete(Long deviceTemplateId) {
        DeviceTemplate deviceTemplate = deviceTemplateMapper.selectById(deviceTemplateId);
        ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceTemplate), "iot模版不存在");
        ClassUtil.throwBusinessException(deviceTemplate.getIsDeleted(), "iot模版已删除");
        deviceTemplateMapper.deleteById(deviceTemplateId);
        return Boolean.TRUE;
    }

    @Override
    public DeviceTemplateVo templateDetail(Long deviceTemplateId) {
        DeviceTemplate deviceTemplate = deviceTemplateMapper.selectById(deviceTemplateId);
        ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceTemplate), "iot模版不存在");
        ClassUtil.throwBusinessException(deviceTemplate.getIsDeleted(), "iot模版已删除");
        DeviceTemplateVo templateVo = BeanUtil.copyProperties(deviceTemplate, DeviceTemplateVo.class);
        templateVo.setManualInIdCardAuth(deviceTemplate.getManualInIdCard() ? deviceTemplate.getManualInIdCardAuth() : null);
        templateVo.setDeviceTemplateId(deviceTemplate.getId());
        return templateVo;
    }
}
