package com.sptg.iot.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.iot.api.beans.ApiResultBean;
import com.sptg.iot.api.beans.IotReturnCode;
import com.sptg.iot.api.beans.PageData;
import com.sptg.iot.api.dto.AlarmNoticeDto;
import com.sptg.iot.api.dto.IotAlarmDto;
import com.sptg.iot.api.dto.IotSmsSendDto;
import com.sptg.iot.api.entity.IotAlarm;
import com.sptg.iot.api.entity.IotAuthentication;
import com.sptg.iot.api.entity.IotDevice;
import com.sptg.iot.api.entity.IotSysConf;
import com.sptg.iot.api.util.IotHttpUtil;
import com.sptg.iot.biz.mapper.IotAlarmMapper;
import com.sptg.iot.biz.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author zwx
 * @create 2020/10/19 23:22
 * 设备告警 服务层实现层
 */
@Service
@RequiredArgsConstructor
public class IotAlarmServiceImpl extends ServiceImpl<IotAlarmMapper, IotAlarm> implements IotAlarmServiceInterface {

    private final IotApiLogServiceInterface iotApiLogServiceInterface;
    private final IotSysConfServiceInterface iotSysConfServiceInterface;
    private final IotAuthServiceInterface iotAuthServiceInterface;
    private final IotDeviceServiceInterface iotDeviceServiceInterface;

    @Override
    public ResultBean<Page<IotAlarm>> showIotAlarmList(IotAlarmDto iotAlarmDto) {
        Page<IotAlarm> page = iotAlarmDto.getPage();
        Wrapper<IotAlarm> wrapper = new EntityWrapper<>();
        page.setRecords(this.baseMapper.getList(wrapper));
        return new ResultBean<>(ResultEnum.SUCCESS, page);
    }

    @Override
    public ResultBean<String> syncIotAlarmList(IotAlarmDto iotDeviceAlarmDto) {
        List<IotSysConf> iotSysConfList = this.iotSysConfServiceInterface.selectList(null);
        List<IotAlarm> allIotAlarmList = new ArrayList<>();
        for(int i = 0; i < iotSysConfList.size(); i++){
            IotSysConf iotSysConf = iotSysConfList.get(i);
            String appId = iotSysConf.getAppId();
            IotAuthentication iotAuthentication = this.iotAuthServiceInterface.findByAppId(iotSysConf.getAppId());
            if(iotAuthentication != null){
                IotHttpUtil httpUtil = new IotHttpUtil(iotSysConf);
                List<IotAlarm> iotAlarmList = new ArrayList<>();
                Map<String, Object> bizParamsMap = BeanUtil.beanToMap(iotDeviceAlarmDto);
                String[] prefixList = iotSysConf.getPrefix().split(",");
                for(int j = 0; j < prefixList.length; j++){
                    String prefix = prefixList[j];
                    String accessToken = iotAuthentication.getAccessToken();
                    ApiResultBean<PageData<IotAlarm>> apiResultBean = httpUtil.syncIotAlarmList(bizParamsMap, prefix, accessToken);
                    if(apiResultBean.getCode().equals(IotReturnCode.UNAUTHORIZED.getCode())){ //未认证，提示先去认证
                        return new ResultBean<>(ResultEnum.FAILURE, IotReturnCode.UNAUTHORIZED.toString());
                    }
                    if(apiResultBean.getCode().equals(OperationConstant.ZERO)){
                        PageData<IotAlarm> pageData = apiResultBean.getData();
                        List<IotAlarm> items = pageData.getItems();
                        items.forEach(iotAlarm -> {
                            iotAlarm.setLastSyncDate(new Date());
                            iotAlarm.setAppId(appId);
                            iotAlarm.setPrefix(prefix);
                        });
                        iotAlarmList.addAll(items);
                        String reqData = JsonUtils.objectToJson(bizParamsMap);
                        this.iotApiLogServiceInterface.recordIotApiLog("/alarm/list", prefix, appId, reqData, apiResultBean);
                    }
                }
                allIotAlarmList.addAll(iotAlarmList); //将改应用ID下的所有设备记录下来
            }
        }
        List<IotAlarm> updateIotAlarmList = new ArrayList<>();
        if(allIotAlarmList.size() > 0){
            allIotAlarmList.forEach(source ->{
                IotAlarm target = this.getIotAlarmByAlarmId(source.getAlarm_id());
                if(target == null){
                    target = new IotAlarm();
                }else{
                    source.setId(target.getId());
                }
                BeanUtil.copyProperties(source, target);
                updateIotAlarmList.add(target);
            });
        }
        boolean result = this.insertOrUpdateBatch(updateIotAlarmList);
        if(result){
            return new ResultBean<>(ResultEnum.SUCCESS, "同步成功");
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "同步成功，但保存失败");
        }
    }

    @Override
    public ResultBean<String> syncIotAlarmDetailOne(IotAlarmDto iotAlarmDto) {
        String appId = iotAlarmDto.getAppId();
        String prefix = iotAlarmDto.getPrefix();
        IotSysConf iotSysConf = this.iotSysConfServiceInterface.findSysConfByAppId(appId);
        IotAuthentication iotAuthentication = this.iotAuthServiceInterface.findByAppId(appId);
        String accessToken = iotAuthentication.getAccessToken();
        IotHttpUtil httpUtil = new IotHttpUtil(iotSysConf);
        Map<String, Object> bizParamsMap = BeanUtil.beanToMap(iotAlarmDto);
        ApiResultBean<IotAlarm> apiResultBean = httpUtil.syncIotAlarmDetail(bizParamsMap, prefix, accessToken);
        if(apiResultBean.getCode().equals(IotReturnCode.UNAUTHORIZED.getCode())){ //未认证，提示先去认证
            return new ResultBean<>(ResultEnum.FAILURE, IotReturnCode.UNAUTHORIZED.toString());
        }
        IotAlarm source = null;
        if(apiResultBean.getCode().equals(OperationConstant.ZERO)){
            source = apiResultBean.getData();
            String reqData = JsonUtils.objectToJson(bizParamsMap);
            this.iotApiLogServiceInterface.recordIotApiLog("/alarm/search", prefix, appId, reqData, apiResultBean);
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, apiResultBean.getMsg());
        }
        IotAlarm target = this.getIotAlarmByAlarmId(source.getAlarm_id());
        if(target == null){
            target = new IotAlarm();
        }else{
            source.setId(target.getId());
        }
        BeanUtil.copyProperties(source, target);
        target.setLastSyncDate(new Date());
        target.setAppId(appId);
        target.setPrefix(prefix);
        boolean result = this.insertOrUpdate(target);
        if(result){
            return new ResultBean<>(ResultEnum.SUCCESS, "同步告警详情成功");
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "同步告警详情成功，但保存失败");
        }
    }

    @Override
    public ResultBean<String> syncIotAlarmDetailBatch(List<IotAlarmDto> iotAlarmDtoList) {
        List<IotAlarm> updateIotAlarmList = new ArrayList<>();
        for(int i = 0; i < iotAlarmDtoList.size(); i++){
            IotAlarmDto iotAlarmDto = iotAlarmDtoList.get(i);
            String appId = iotAlarmDto.getAppId();
            String prefix = iotAlarmDto.getPrefix();
            IotSysConf iotSysConf = this.iotSysConfServiceInterface.findSysConfByAppId(appId);
            IotAuthentication iotAuthentication = this.iotAuthServiceInterface.findByAppId(appId);
            String accessToken = iotAuthentication.getAccessToken();
            IotHttpUtil httpUtil = new IotHttpUtil(iotSysConf);
            Map<String, Object> bizParamsMap = BeanUtil.beanToMap(iotAlarmDto);
            ApiResultBean<IotAlarm> apiResultBean = httpUtil.syncIotAlarmDetail(bizParamsMap, prefix, accessToken);
            if(apiResultBean.getCode().equals(IotReturnCode.UNAUTHORIZED.getCode())){ //未认证，提示先去认证
                return new ResultBean<>(ResultEnum.FAILURE, IotReturnCode.UNAUTHORIZED.toString());
            }
            String reqData = JsonUtils.objectToJson(iotAlarmDto);
            this.iotApiLogServiceInterface.recordIotApiLog("/alarm/search", prefix, appId, reqData, apiResultBean);
            if(apiResultBean.getCode().equals(OperationConstant.ZERO)){
                IotAlarm source = apiResultBean.getData();
                if(source != null){
                    IotAlarm target = this.getIotAlarmByAlarmId(source.getAlarm_id());
                    source.setId(null);
                    if(target == null){
                        target = new IotAlarm();
                    }else{
                        source.setId(target.getId());
                    }
                    BeanUtil.copyProperties(source, target);
                    target.setLastSyncDate(new Date());
                    target.setAppId(appId);
                    target.setPrefix(prefix);
                    updateIotAlarmList.add(target);
                }
            }
        }
        if(updateIotAlarmList.size() > 0){
            boolean b = this.insertOrUpdateBatch(updateIotAlarmList);
            if(b){
                return new ResultBean<>(ResultEnum.SUCCESS, "批量同步告警详情成功");
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, "批量同步告警详情成功，但保存失败");
            }
        }else{
            return new ResultBean<>(ResultEnum.SUCCESS, "批量同步告警详情失败，请查看同步日志");
        }
    }

    @Override
    public ResultBean<String> syncIotAlarmDetailAll(IotAlarmDto iotAlarmDto) {
        List<IotAlarm> updateIotAlarmList = new ArrayList<>();
        Wrapper<IotAlarm> wrapper = new EntityWrapper<>();
        List<IotAlarm> iotAlarmList = this.getList(wrapper);
        for(int i = 0; i < iotAlarmList.size(); i++){
            IotAlarm iotAlarm = iotAlarmList.get(i);
            String appId = iotAlarm.getAppId();
            String prefix = iotAlarm.getPrefix();
            IotSysConf iotSysConf = this.iotSysConfServiceInterface.findSysConfByAppId(appId);
            IotAuthentication iotAuthentication = this.iotAuthServiceInterface.findByAppId(appId);
            String accessToken = iotAuthentication.getAccessToken();
            IotHttpUtil httpUtil = new IotHttpUtil(iotSysConf);
            Map<String, Object> bizParamsMap = BeanUtil.beanToMap(iotAlarm);
            ApiResultBean<IotAlarm> apiResultBean = httpUtil.syncIotAlarmDetail(bizParamsMap, prefix, accessToken);
            if(apiResultBean.getCode().equals(IotReturnCode.UNAUTHORIZED.getCode())){ //未认证，提示先去认证
                return new ResultBean<>(ResultEnum.FAILURE, IotReturnCode.UNAUTHORIZED.toString());
            }
            String reqData = JsonUtils.objectToJson(iotAlarm);
            this.iotApiLogServiceInterface.recordIotApiLog("/alarm/search", prefix, appId, reqData, apiResultBean);
            if(apiResultBean.getCode().equals(OperationConstant.ZERO)){
                IotAlarm source = apiResultBean.getData();
                if(source != null){
                    IotAlarm target = this.getIotAlarmByAlarmId(source.getAlarm_id());
                    source.setId(null);
                    if(target == null){
                        target = new IotAlarm();
                    }else{
                        source.setId(target.getId());
                    }
                    BeanUtil.copyProperties(source, target);
                    target.setLastSyncDate(new Date());
                    target.setAppId(appId);
                    target.setPrefix(prefix);
                    updateIotAlarmList.add(target);
                }
            }
        }
        if(updateIotAlarmList.size() > 0){
            boolean b = this.insertOrUpdateBatch(updateIotAlarmList);
            if(b){
                return new ResultBean<>(ResultEnum.SUCCESS, "全量同步告警详情成功");
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, "全量同步告警详情成功，但保存失败");
            }
        }else{
        return new ResultBean<>(ResultEnum.SUCCESS, "全量同步告警详情失败，请查看同步日志");
        }
    }

    @Override
    public IotAlarm getIotAlarmByAlarmId(String alarmId) {
        Wrapper<IotAlarm> wrapper = new EntityWrapper<>();
        wrapper.eq("s_alarm_id", alarmId);
        return this.baseMapper.getOne(wrapper);
    }

    @Override
    public List<IotAlarm> getList(Wrapper<IotAlarm> wrapper) {
        return this.baseMapper.getList(wrapper);
    }

    @Override
    public ResultBean<Page<IotAlarm>> pagingQuery(IotAlarmDto iotAlarmDto) {
        Page<IotAlarm> page = iotAlarmDto.getPage();
        Wrapper<IotAlarm> wrapper = new EntityWrapper<>();
        String device_id = iotAlarmDto.getDevice_id();
        String device_name = iotAlarmDto.getDevice_name();
        String name = iotAlarmDto.getName();
        String level = iotAlarmDto.getLevel();
        Integer status = iotAlarmDto.getStatus();
        if(StringUtils.hasText(device_id)){
            wrapper.eq("s_device_id", device_id);
        }
        if(StringUtils.hasText(device_id)){
            wrapper.eq("s_device_name", device_name);
        }
        if(status != null){
            wrapper.eq("i_status", status);
        }
        if(StringUtils.hasText(name)){
            wrapper.eq("s_name", name);
        }
        if(StringUtils.hasText(level)){
            wrapper.eq("s_level", level);
        }
        page.setRecords(this.baseMapper.pagingQuery(wrapper, iotAlarmDto.getPage()));
        return new ResultBean<>(ResultEnum.SUCCESS,page);
    }

    @Override
    public IotAlarm getIotAlarmById(Long id) {
        Wrapper<IotAlarm> wrapper = new EntityWrapper<>();
        wrapper.eq("l_id", id);
        IotAlarm iotAlarm = this.baseMapper.getOne(wrapper);
        return iotAlarm;
    }

    @Override
    public ResultBean<String> alarmNotice(List<AlarmNoticeDto> alarmNoticeDtoList) {
        List<IotAlarm> targetList = new ArrayList<>();
        for(int i = 0; i < alarmNoticeDtoList.size(); i++){
            AlarmNoticeDto source = alarmNoticeDtoList.get(i);
            String alarm_id = source.getAlarm_id();
            IotAlarm target = this.getIotAlarmByAlarmId(alarm_id);
            IotDevice iotDevice = this.iotDeviceServiceInterface.getIotDeviceByDeviceId(source.getDevice_id());
            if(target == null){
                target = new IotAlarm();
                target.setAlarm_id(alarm_id);
                target.setAlarm_times(0);
                target.setRecord_time(source.getReceive_time());
            }
            target.setAlarm_times(target.getAlarm_times() + 1);
            target.setLevel(source.getLevel());
            target.setAlarm_desc(source.getAlarm_desc());
            target.setName(source.getAlarm_desc());
            if(iotDevice != null){
                target.setDevice_id(source.getDevice_id());
                target.setDevice_name(iotDevice.getDevice_name());
                target.setDevice_type(iotDevice.getDevice_type());
                target.setType_name(iotDevice.getType_name());
                source.setPrefix(iotDevice.getPrefix());
            }
            target.setAlarm_type(source.getType());
            target.setUpdate_time(source.getReceive_time());
            target.setMetric(source.getMetric());
            target.setAlarm_metric(source.getAlarm_metric());
            target.setAlarm_value(source.getAlarm_value());
            target.setIs_alarm(source.getIs_alarm());
            target.setLastNoticeDate(new Date());
            target.setMonitorValue(source.getAlarm_value());
            targetList.add(target);
        }
        boolean b = this.insertOrUpdateBatch(targetList);
        if(b){
            return new ResultBean<>(ResultEnum.SUCCESS, "批量保存成功");
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "批量保存失败");
        }

    }

    @Override
    public ResultBean<Boolean> alarmSendSms(IotSmsSendDto iotSmsSendDto) {
        IotSysConf sysConf = this.iotSysConfServiceInterface.findSysConfById(1L);
        String appId = sysConf.getAppId();
        IotAuthentication auth = this.iotAuthServiceInterface.findByAppId(appId);
        String prefix = iotSmsSendDto.getPrefix();
        IotHttpUtil httpUtil = new IotHttpUtil(sysConf);
        Map<String, Object> bizParamsMap = BeanUtil.beanToMap(iotSmsSendDto);
        ApiResultBean apiResultBean = httpUtil.iotAlarmSendSms(bizParamsMap, prefix, auth.getAccessToken());
        String reqData = JsonUtils.objectToJson(iotSmsSendDto);
        this.iotApiLogServiceInterface.recordIotApiLog("/sms/sendSms", prefix, appId, reqData, apiResultBean);
        return ResultBean.ok();
    }
}
