package com.sptg.third.biz.grid.controller;

import cn.hutool.json.JSONUtil;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.iot.api.dto.AlarmNoticeDto;
import com.sptg.iot.api.entity.IotDevice;
import com.sptg.iot.api.feigns.IotDeviceFeign;
import com.sptg.third.api.contants.UrlContants;
import com.sptg.third.api.entity.grid.GridConfig;
import com.sptg.third.api.feigns.grid.GridIotFeign;
import com.sptg.third.biz.grid.service.GridConfigServiceInterface;
import com.sptg.video.cloud.api.entity.VCDevice;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.*;

/**
 * @author zwx
 * @create 2020/11/28 20:23
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class GridIotController implements GridIotFeign {

    private final GridConfigServiceInterface gridConfigServiceInterface;
    private final RestTemplate restTemplate;
    private final IotDeviceFeign iotDeviceFeign;

    /**
     * 推送物联网设备到网格
     * @return
     */
    @Override
    @PostMapping(value = "/third/grid/iot/device/increment/push")
    public ResultBean<String> gridIotDeviceIncrementPush() {
        GridConfig gridConfig = this.gridConfigServiceInterface.getById(1L);
        ResultBean<List<IotDevice>> resultBean = this.iotDeviceFeign.getList();
        List<IotDevice> iotDeviceList = resultBean.getData();
        List<Map<String, Object>> mapList = new ArrayList<>();
        List<IotDevice> neverPushList = new ArrayList<>();
        for(int i = 0; i < iotDeviceList.size(); i++){
            IotDevice iotDevice = iotDeviceList.get(i);
            if(iotDevice.getLastPushDate() == null){
                Map<String, Object> map = this.buildGridIotDeviceData(iotDevice);
                mapList.add(map);
                neverPushList.add(iotDevice);
            }
        }
        if(mapList.size() > 0){
            Map resultMap = getRequestResult(mapList, gridConfig, UrlContants.Grid.IOT_DEVICE_SYNC);
            if(resultMap.get("code").equals(200)){
                for(int i = 0; i < neverPushList.size(); i++){
                    IotDevice iotDevice = neverPushList.get(i);
                    iotDevice.setLastPushDate(new Date());
                }
                this.iotDeviceFeign.updateBatch(neverPushList);
                return new ResultBean<>(ResultEnum.SUCCESS);
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, (String) resultMap.get("msg"));
            }
        }else{
            return new ResultBean<>(ResultEnum.SUCCESS);
        }
    }

    @Override
    @PostMapping(value = "/third/grid/iot/device/total/push")
    public ResultBean<String> gridIotDeviceTotalPush() {
        GridConfig gridConfig = this.gridConfigServiceInterface.getById(1L);
        ResultBean<List<IotDevice>> resultBean = this.iotDeviceFeign.getList();
        List<IotDevice> iotDeviceList = resultBean.getData();
        List<Map<String, Object>> mapList = new ArrayList<>();
        for(int i = 0; i < iotDeviceList.size(); i++){
            IotDevice iotDevice = iotDeviceList.get(i);
            Map<String, Object> map = this.buildGridIotDeviceData(iotDevice);
            mapList.add(map);
        }
        if(mapList.size() > 0){
            Map resultMap = getRequestResult(mapList, gridConfig, UrlContants.Grid.IOT_DEVICE_SYNC);
            if(resultMap.get("code").equals(200)){
                for(int i = 0; i < iotDeviceList.size(); i++){
                    IotDevice iotDevice = iotDeviceList.get(i);
                    iotDevice.setLastPushDate(new Date());
                }
                this.iotDeviceFeign.updateBatch(iotDeviceList);
                return new ResultBean<>(ResultEnum.SUCCESS);
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, (String) resultMap.get("msg"));
            }
        }else{
            return new ResultBean<>(ResultEnum.SUCCESS);
        }
    }

    /**
     * 推送指定物联网设备到网格
     * @return
     */
    @Override
    @PostMapping(value = "/third/grid/iot/device/push")
    public ResultBean<String> gridIotDevicePush(@RequestBody List<IotDevice> iotDeviceList) {
        GridConfig gridConfig = this.gridConfigServiceInterface.getById(1L);
        List<Map<String, Object>> mapList = new ArrayList<>();
        for(int i = 0; i < iotDeviceList.size(); i++){
            IotDevice iotDevice = iotDeviceList.get(i);
            if(iotDevice.getLastPushDate() == null){
                Map<String, Object> map = this.buildGridIotDeviceData(iotDevice);
                mapList.add(map);
            }
        }
        if(mapList.size() > 0){
            Map resultMap = getRequestResult(mapList, gridConfig, UrlContants.Grid.IOT_DEVICE_SYNC);
            if(resultMap.get("code").equals(200)){
                for(int i = 0; i < iotDeviceList.size(); i++){
                    IotDevice iotDevice = iotDeviceList.get(i);
                    iotDevice.setLastPushDate(new Date());
                }
                this.iotDeviceFeign.updateBatch(iotDeviceList);
                return new ResultBean<>(ResultEnum.SUCCESS);
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, (String) resultMap.get("msg"));
            }
        }else{
            return new ResultBean<>(ResultEnum.SUCCESS);
        }
    }

    @Override
    @PostMapping(value = "/third/grid/iot/device/heartbeat/push")
    public ResultBean<String> gridIotDeviceHeartbeatPush(@RequestBody IotDevice iotDevice) {
        GridConfig gridConfig = this.gridConfigServiceInterface.getById(1L);
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map<String, Object> map = this.buildGridIotDeviceData(iotDevice);
        mapList.add(map);
        if(mapList.size() > 0){
            Map resultMap = getRequestResult(mapList, gridConfig, UrlContants.Grid.IOT_DEVICE_SYNC);
            if(resultMap.get("code").equals(200)){
                return new ResultBean<>(ResultEnum.SUCCESS);
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, (String) resultMap.get("msg"));
            }
        }else{
            return new ResultBean<>(ResultEnum.SUCCESS);
        }
    }

    @Override
    @PostMapping(value = "/third/grid/iot/device/status/push")
    public ResultBean<String> gridIotDeviceStatusPush(@RequestBody IotDevice iotDevice) {
        GridConfig gridConfig = this.gridConfigServiceInterface.getById(1L);
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map<String, Object> map = this.buildGridIotDeviceData(iotDevice);
        mapList.add(map);
        if(mapList.size() > 0){
            Map resultMap = getRequestResult(mapList, gridConfig, UrlContants.Grid.IOT_DEVICE_SYNC);
            if(resultMap.get("code").equals(200)){
                return new ResultBean<>(ResultEnum.SUCCESS);
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, (String) resultMap.get("msg"));
            }
        }else{
            return new ResultBean<>(ResultEnum.SUCCESS);
        }
    }

    /**
     * 推送物联网设备告警到网格
     * @param alarmNoticeDtoList
     * @return
     */
    @Override
    @PostMapping(value = "/third/grid/alarm/push")
    public ResultBean<String> gridIotAlarmPush(@RequestBody List<AlarmNoticeDto> alarmNoticeDtoList) {
        GridConfig gridConfig = this.gridConfigServiceInterface.getById(1L);
        List<Map<String, Object>> mapList = new ArrayList<>();
        alarmNoticeDtoList.forEach(alarmNoticeDto -> {
            Map<String, Object> map = buildGridIotAlarmData(alarmNoticeDto);
            mapList.add(map);
        });
        Map resultMap = getRequestResult(mapList, gridConfig, UrlContants.Grid.IOT_ALARM_SYNC);
        if(resultMap.get("code").equals(200)){
            return new ResultBean<>(ResultEnum.SUCCESS);
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, (String) resultMap.get("msg"));
        }
    }

    /**
     * 构建网格物联网设备接收对象
     * @param iotDevice
     * @return
     */
    private Map<String, Object> buildGridIotDeviceData(IotDevice iotDevice){
        Map<String, Object> map = new HashMap<>();
        map.put("oldId", iotDevice.getId());
        map.put("deviceId", iotDevice.getDevice_id());
        map.put("deviceName", iotDevice.getDevice_name());
        map.put("manufacturersNo", iotDevice.getManufacturers_no());
        map.put("manufacturers", iotDevice.getManufacturer());
        map.put("defenseStatus", iotDevice.getDefense_status());
        map.put("deviceType", iotDevice.getDevice_type());
        map.put("deviceStatus", iotDevice.getStatus());
        map.put("typeName", iotDevice.getType_name());
        map.put("latitudeLongitude", iotDevice.getLatitude_longitude());
        map.put("deviceInstallAddress", iotDevice.getDevice_install_address());
        map.put("distLocate", iotDevice.getDist_locate());
        map.put("tag", iotDevice.getTag());
        map.put("deviceSpecld", iotDevice.getDevice_specld());
        map.put("deviceSpecName", iotDevice.getDevice_specname());
        map.put("protocolType", iotDevice.getProtocol_type());
        map.put("masterKey", iotDevice.getMaster_key());
        map.put("productId", iotDevice.getProduct_id());
        map.put("deviceServerId", iotDevice.getDevice_server_id());
        map.put("area", iotDevice.getArea());
        map.put("personId", iotDevice.getPerson_id());
        map.put("organization", iotDevice.getOrganization());
        map.put("deviceImage", iotDevice.getDevice_image());
        map.put("specialData", iotDevice.getSpecialData());
        map.put("monitorValue", iotDevice.getMonitorValue());
        map.put("concentration", iotDevice.getMonitorValue());
        map.put("battery", iotDevice.getBattery_value());
        map.put("signalIntensity", iotDevice.getSignal_intensity());
        map.put("tenantId", iotDevice.getTenantId());
        map.put("imei", iotDevice.getIMEI());
        map.put("isAep", iotDevice.getIs_aep());
        return map;
    }

    /**
     * 构建网格物联网设备告警接收对象
     * @param alarmNoticeDto
     * @return
     */
    private Map<String, Object> buildGridIotAlarmData(AlarmNoticeDto alarmNoticeDto){
        Map<String, Object> map = new HashMap<>();
        map.put("alarmId", alarmNoticeDto.getAlarm_id());
        map.put("alarmDesc", alarmNoticeDto.getAlarm_desc());
        map.put("level", alarmNoticeDto.getLevel());
        map.put("alarmValue", alarmNoticeDto.getAlarm_value());
        map.put("alarmName", alarmNoticeDto.getAlarm_desc());
        map.put("deviceId", alarmNoticeDto.getDevice_id());
        map.put("recordTime", alarmNoticeDto.getReceive_time());
        map.put("type", alarmNoticeDto.getType());
        map.put("prefix", alarmNoticeDto.getPrefix());
        return map;
    }

    /**
     * 获取请求结果
     * @param mapList  请求体
     * @param gridConfig host+port
     * @param apiPath 请求路径
     * @return
     */
    private Map getRequestResult(List<Map<String, Object>> mapList, GridConfig gridConfig, String apiPath){
        ResponseEntity responseEntity = null;
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE,"application/json;charset=UTF-8");
        headers.add("Blade-Auth",gridConfig.getToken());
        HttpEntity<String> requestEntity = new HttpEntity<String>(JSONUtil.toJsonStr(mapList), headers);
        ParameterizedTypeReference<Object> reference = new ParameterizedTypeReference<Object>() {
        };
        String url = gridConfig.getGridHost()+":"+gridConfig.getGridPort()+apiPath;
        URI uri = URI.create(url);
        responseEntity = this.restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        return (Map) responseEntity.getBody();
    }
}
