package com.zcxk.charge.web.controller;

import com.zcxk.charge.api.dto.query.MonitorInfoDto;
import com.zcxk.charge.api.enums.ChargeErrorEnum;
import com.zcxk.charge.api.dto.AlarmDetailsDto;
import com.zcxk.charge.api.dto.SceneUsageDto;
import com.zcxk.charge.api.vo.AlarmDetailsEntityVo;
import com.zcxk.charge.core.entity.*;
import com.zcxk.charge.web.service.*;
import com.zcxk.core.common.enums.RespCodeEnum;
import com.zcxk.core.common.pojo.AjaxMessage;
import com.zcxk.core.oauth2.pojo.LoginUser;
import com.zcxk.core.oauth2.util.UserUtil;
import com.zcxk.core.utils.BigDecimalUtils;
import com.zcxk.core.utils.ByteArrayUtils;
import com.zcxk.core.utils.util.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;

/**
 * 标签信息页面控制器
 * @author WYY
 * @date 2020-12-02 09:29
 */
@RestController
@RequestMapping("/monitorinfo")
@Api(tags = "标签信息")
public class MonitorInfoController {

    @Autowired
    private MonitorInfoService monitorInfoService;

    @Autowired
    private DeviceParmService deviceParmService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private AlarmDetailsService alarmDetailsService;

    @Autowired
    private DeviceAttributeSpecsService deviceAttributeSpecsService;

    @Autowired
    private DeviceAttributeService deviceAttributeService;

    @Autowired
    private MonitorDataReportService monitorDataReportService;

    @Autowired
    private DeviceSetupMethodService deviceSetupMethodService;

    @Autowired
    private DeviceSetupRecordService deviceSetupRecordService;


    @ApiOperation(value = "按场景ID查询供水量出水量耗药量耗电量")
    @RequestMapping(value = "/findTotalUsageBySceneIdForComDsiplay", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage findTotalUsageBySceneIdForComDsiplay(@ApiParam(value = "场景ID", required = true) @RequestParam Long id,
                                                            @ApiParam(value = "场景类型(0水源 1水厂 2泵站)") @RequestParam(required = false) Integer type) {
        SceneUsageDto sceneUsageDto = new SceneUsageDto();

        // 查询场景下的所有设备信息
        BigDecimal amount1 = monitorDataReportService.getAmountCount( id.intValue(), 3, 1);
        sceneUsageDto.setYieldWaterUsage(amount1 != null ? amount1.doubleValue() : 0);

        BigDecimal amount2 = monitorDataReportService.getAmountCount(id.intValue(),4, 1);
        sceneUsageDto.setIntakeWaterUsage(amount2 != null ? amount2.doubleValue() : 0);

        BigDecimal amount3 = monitorDataReportService.getAmountCount( id.intValue(),  5, 1);
        sceneUsageDto.setPowerUsage(amount3 != null ? amount3.doubleValue() : 0);

        BigDecimal amount4 = monitorDataReportService.getAmountCount(id.intValue(), 6, 1);
        sceneUsageDto.setDrugUsage(amount4 != null ? amount4.doubleValue() : 0);

        sceneUsageDto.setCollectDate(monitorDataReportService.getLastCollectTime(null, id.intValue(),null));

        if (type.equals(1) || type.equals(0)) {
            sceneUsageDto.setYieldWaterUsage(BigDecimalUtils.divideToDouble(sceneUsageDto.getYieldWaterUsage(),10000, 3));
            sceneUsageDto.setIntakeWaterUsage(BigDecimalUtils.divideToDouble(sceneUsageDto.getIntakeWaterUsage(),10000, 3));
            sceneUsageDto.setPowerUsage(BigDecimalUtils.divideToDouble(sceneUsageDto.getPowerUsage(),10000, 3));
            sceneUsageDto.setDrugUsage(BigDecimalUtils.divideToDouble(sceneUsageDto.getDrugUsage(),10000, 3));
        } else {
            sceneUsageDto.setYieldWaterUsage(BigDecimalUtils.setScaleToDouble(sceneUsageDto.getYieldWaterUsage(), 3));
            sceneUsageDto.setIntakeWaterUsage(BigDecimalUtils.setScaleToDouble(sceneUsageDto.getIntakeWaterUsage(), 3));
            sceneUsageDto.setPowerUsage(BigDecimalUtils.setScaleToDouble(sceneUsageDto.getPowerUsage(), 3));
            sceneUsageDto.setDrugUsage(BigDecimalUtils.setScaleToDouble(sceneUsageDto.getDrugUsage(), 3));
        }
        return AjaxMessage.success(sceneUsageDto);
    }

    @ApiOperation(value = "按场景ID查询所有标签信息")
    @RequestMapping(value = "/findBySceneId", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<List<MonitorInfoEntity>> findBySceneId(@RequestBody @Valid MonitorInfoDto dto) {
        MonitorInfoEntity monitorInfoEntity = new MonitorInfoEntity();
        monitorInfoEntity.setSceneId(dto.getId());
        monitorInfoEntity.setImageType(dto.getImageType());
        monitorInfoEntity.setType(dto.getType());
        monitorInfoEntity.setDeviceId(dto.getDeviceId());
        List<MonitorInfoEntity> page = monitorInfoService.findList(monitorInfoEntity);
        for (MonitorInfoEntity item : page) {
            switch (item.getMonitorType().intValue()) {
                case 0:
                    getMonitorInfo(dto.getId(), item);
                    break;
                case 3:
                    updateCommonState(dto.getId(), 3, item);
                    break;
                case 4:
                    updateCommonState(dto.getId(), 4, item);
                    break;
                case 5:
                    updateCommonState(dto.getId(), 5, item);
                    break;
                default:
                    break;
            }
        }
        return AjaxMessage.success(page);
    }

    /**
     * 更新指令状态
     * @param sceneId
     * @param item
     */
    public void updateCommonState(Long sceneId, Integer type, MonitorInfoEntity item) {
        DeviceSetupRecordEntity parm = new DeviceSetupRecordEntity();
        parm.setDeviceId(item.getDeviceId());
        parm.setAttributeId(item.getAttributeId());
        parm.setType(type);
        if (type == 4 || type == 3) {
            // 更新压力值或状态值 泵状态0关 1开 TODO 后续需要统一
            BigDecimal value = monitorDataReportService.getDeviceAttributeValue(item.getDeviceCode(), item.getAttributeId());
            item.setAttributeValue(BigDecimalUtils.setScaleToDouble(value, 3));
        }
        // 查询报警信息
        List<AlarmDetailsEntityVo> alarmDetailsDtos = alarmDetailsService.selectByDeviceAttributeId(sceneId, item.getDeviceId().intValue(), item.getAttributeId().intValue());
        if (alarmDetailsDtos.size() > 0) {
            item.setIsAlarm(1);
        } else {
            item.setIsAlarm(0);
        }
        DeviceSetupRecordEntity recordEntity = deviceSetupRecordService.selectLastOne(parm);
        if (recordEntity != null) {
            item.setCommonState(recordEntity.getState());
        }
    }

    /**
     * 更新标签值
     * @param sceneId
     * @param item
     */
    public void getMonitorInfo(Long sceneId, MonitorInfoEntity item) {
        // 查询报警信息
        List<AlarmDetailsEntityVo> alarmDetailsDtos = alarmDetailsService.selectByDeviceId(sceneId, item.getDeviceId().intValue());
        Map<Integer, AlarmDetailsEntityVo> mapAlarm = new HashMap<>(alarmDetailsDtos.size());
        // 将缓存中的实时数据放到map中方便进行遍历
        for (AlarmDetailsEntityVo alarmDetailsDto : alarmDetailsDtos) {
            mapAlarm.put(alarmDetailsDto.getAttributeId(), alarmDetailsDto);
        }
        byte[] bytes = redisUtil.get(("sms_water_" + item.getDeviceCode()).getBytes());
        if (bytes == null || bytes.length == 0) {
            return;
        }
        MonitorDataEntity monitorDataEntity = (MonitorDataEntity) ByteArrayUtils.bytesToObject(bytes).get();
        Map<Long, MonitorDataValueEntity> map = new HashMap<>();
        // 将缓存中的实时数据放到map中方便进行遍历
        for (MonitorDataValueEntity dateValue : monitorDataEntity.getDataValues()) {
            map.put(dateValue.getAttributeId(), dateValue);
        }
        // 判断如果是标签则进行map中取值//标签
        if (!item.getMonitorType().equals(0L)){
            return;
        }
        //按属性ID查询标签值
        DeviceAttributeSpecsEntity deviceAttributeSpecsEntity = new DeviceAttributeSpecsEntity();
        deviceAttributeSpecsEntity.setAttributeId(item.getAttributeId());
        List<DeviceAttributeSpecsEntity> deviceAttributeSpecsEntities = deviceAttributeSpecsService.findList(deviceAttributeSpecsEntity);
        if (map.containsKey(item.getAttributeId())) {
            Double value = map.get(item.getAttributeId()).getDataValue();
            if (value != null) {
                if (deviceAttributeSpecsEntities.size() > 0) {
                    for (DeviceAttributeSpecsEntity specsEntity : deviceAttributeSpecsEntities) {
                        if (Integer.valueOf(specsEntity.getSpecsValue()) == value.intValue()) {
                            item.setMonitorValue(specsEntity.getSpecsName());
                        }
                    }
                } else {
                    DeviceAttributeEntity deviceAttributeEntity = deviceAttributeService.getById(item.getAttributeId());
                    String unit = "";
                    if (deviceAttributeEntity != null && deviceAttributeEntity.getUnit() != null) {
                        unit = deviceAttributeEntity.getUnit();
                    }
                    item.setMonitorValue(String.format("%.3f", map.get(item.getAttributeId()).getDataValue()) + unit);
                }
            }
        }
        // 判断是否报警
        if (mapAlarm.containsKey(item.getAttributeId().intValue())) {
            item.setIsAlarm(1);
            item.setMonitorValue(item.getMonitorValue() + "(" + mapAlarm.get(item.getAttributeId().intValue()).getAlarmRange() + ")");
        } else {
            item.setIsAlarm(0);
        }
    }

    @RequestMapping(value = "getDeviceParmByDeviceId", method = RequestMethod.GET)
    @ApiOperation(value = "查询单个设备参数信息(标签设置)")
    public AjaxMessage<List<DeviceParmEntity>> getByDeviceId(@ApiParam(value = "场景id", required = true) @RequestParam Integer sceneId,
                                                             @ApiParam(value = "设备id", required = true) @RequestParam Integer id) {
        return AjaxMessage.success( deviceParmService.selectByDeviceIdForGis(sceneId, id));
    }

    @ApiOperation(value = "单个新增")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage addMonitorInfo(@ApiParam(value = "标签信息", required = true) @RequestBody MonitorInfoEntity monitorInfo) {
        LoginUser currentUser = UserUtil.getCurrentUser();
        monitorInfo.setTenantId(currentUser.getTenantId());
        monitorInfo.setStatus(1);
        monitorInfo.setDateCreate(new Date());
        monitorInfo.setDateUpdate(new Date());
        monitorInfo.setCreateBy(currentUser.getName());
        monitorInfo.setUpdateBy(currentUser.getName());
        //校验参数
        int result = monitorInfoService.addMonitorInfo(monitorInfo) ? 1 : 0;
        return AjaxMessage.success(result);
    }

    @RequestMapping(value = "/batchAdd", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "批量新增或修改(按设备)")
    public AjaxMessage addMonitorInfo(@ApiParam(value = "标签信息", required = true) @RequestBody ArrayList<MonitorInfoEntity> monitorInfos) {
        LoginUser currentUser = UserUtil.getCurrentUser();
        if (monitorInfos.size() == 0) {
            return AjaxMessage.success(ChargeErrorEnum.DEVICE_PARENT_ALREADY_EXISTS);
        }
        for (MonitorInfoEntity item : monitorInfos) {
            item.setTenantId(currentUser.getTenantId());
            item.setStatus(1);
            item.setDateCreate(new Date());
            item.setDateUpdate(new Date());
            item.setCreateBy(currentUser.getName());
            item.setUpdateBy(currentUser.getName());
        }
        int result = monitorInfoService.saveOrUpdateBatch(monitorInfos) ? 1 : 0;
        return AjaxMessage.success(result);
    }

    @ApiOperation(value = "按ID查询标签")
    @RequestMapping(value = "/selectById", method = RequestMethod.GET)
    public AjaxMessage selectById(@ApiParam(value = "ID", required = true) @RequestParam Long id) {
        return AjaxMessage.success(monitorInfoService.findMonitorInfoById(id));
    }

    @ApiOperation(value = "单个编辑")
    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage editMonitorInfo(@ApiParam(value = "标签信息", required = true) @RequestBody MonitorInfoEntity monitorInfo) {
        int result = monitorInfoService.updateMonitorInfoById(monitorInfo) ? 1 : 0;
        return AjaxMessage.success(result);
    }

    @ApiOperation(value = "批量删除")
    @RequestMapping(value = "/deleteByIds", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage del(@ApiParam(value = "场景类型ID", required = true) @RequestBody Long[] ids) {
        int result = monitorInfoService.delMonitorInfoByIds(ids) ? 1 : 0;
        return AjaxMessage.success( result);
    }

    @ApiOperation(value = "操作标签--查询设备属性")
    @RequestMapping(value = "/getSceneParmBySceneId", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage getSceneParmBySceneId(@ApiParam(value = "场景类型ID", required = true) @RequestParam Long id) {
        return AjaxMessage.success(deviceParmService.selectByScendId(id.intValue()));
    }

    @ApiOperation(value = "操作标签--进行指令操作")
    @RequestMapping(value = "/setSetupForDevice", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage setSetupForDevice(
            @ApiParam(value = "标签ID", required = true) @RequestParam Long id,
            @ApiParam(value = "参数", required = true) @RequestParam String parms,
            @ApiParam(value = "密钥", required = true) @RequestParam String password) {
        // 校验密钥
        if (!deviceSetupMethodService.checkPassword(password)) {
            return AjaxMessage.success(ChargeErrorEnum.OP_PASSWORD_ERROR);
        }
        //查询操作方法
        try {
            MonitorInfoEntity monitorInfo = monitorInfoService.findMonitorInfoById(id);
            if (monitorInfo != null) {
                Integer type = monitorInfo.getMonitorType().intValue();
                long deviceId = monitorInfo.getDeviceId();
                long attributeId = monitorInfo.getAttributeId();
                long sceneId = monitorInfo.getSceneId();
                int result = deviceSetupMethodService.setSetupForDevice(type, sceneId, deviceId, attributeId, parms) ? 1 : 0;
                return AjaxMessage.success(result);
            }
        } catch (Exception ex) {
            return AjaxMessage.fail(RespCodeEnum.ERROR_500);
        }
        return AjaxMessage.success(0);
    }
}
