package com.ho.business.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.Device;
import com.ho.business.entity.Station;
import com.ho.business.service.DeviceService;
import com.ho.business.service.PvStationService;
import com.ho.business.service.StationService;
import com.ho.business.vo.req.DeviceReqVO;
import com.ho.business.vo.req.StationCurveReq;
import com.ho.business.vo.req.StationReq;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.InverterResp.InverterRespVO;
import com.ho.business.vo.resp.InverterResp.PVStationPanelRespVO;
import com.ho.business.vo.resp.InverterResp.PowerGenerateRespVO;
import com.ho.business.vo.resp.InverterResp.RealtimeCurveRespVO;
import com.ho.business.vo.resp.cockpit.CockForStationResp;
import com.ho.business.vo.resp.station.*;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.ContextConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.BigDecimalUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
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 javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author fancl
 * @desc: 光伏电站
 * @date 2023/1/6
 */
@RestController
@RequestMapping(ContextConstant.BUSINESS + "pvStation")
@Api(tags = "光伏电站")
@Slf4j
public class PVStationController {

    @Autowired
    RedisService redisService;

    @Autowired
    PvStationService pvStationService;

    @Autowired
    BigDecimalUtil bigDecimalUtil;

    @Autowired
    private StationService stationService;

    @Autowired
    DeviceService deviceService;

    @PostMapping("/pvPanel")
    @ApiOperation(value = "光伏面板数据")
    @Cacheable(cacheManager = "towMinuteCacheManager", value = "pvPanel", key = "#stationReq.stationId", sync = true)
    public DataResult<PVStationPanelRespVO> pvPanel(@RequestBody StationReq stationReq) {
        log.info("进入pvPanel");
        Integer stationId = stationReq.getStationId();
        //查电站下的逆变器
        List<DeviceRespVO> deviceRespVOS = pvStationService.getIntervalsByStationId(stationReq.getStationId());
        // 电站数据来自于各个逆变器
        PVStationPanelRespVO pvPanel = pvStationService.getPvPanel(stationId, deviceRespVOS);
        //返回值的BigDecimal类型保留两位小数,并且把null值赋予0
        bigDecimalUtil.keepTwoDecimalPlaces(pvPanel);
        bigDecimalUtil.ifIsNUll(pvPanel);
        //增加3种设备清单 逆变器 inverter ,电表 ,气象仪
        //根据实际设备来查

        List<StationDeviceEquipment> equipments = new ArrayList<>();
        //1.查是否有逆变器
        DeviceReqVO deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(stationId);
        deviceReqVO.setDeviceTypePrefix(DeviceTypeConstant.INVERTER_PREFIX);
        List<DeviceRespVO> inverters = deviceService.getList(deviceReqVO);
        if(!inverters.isEmpty()){
            StationDeviceEquipment inverter = new StationDeviceEquipment();
            inverter.setType("inverter");
            inverter.setName("逆变器");
            equipments.add(inverter);
        }
        //2.电表
        deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(stationId);
        deviceReqVO.setDeviceType(DeviceTypeConstant.COMMON_ELEMETER);
        List<DeviceRespVO> meters = deviceService.getList(deviceReqVO);
        if(!meters.isEmpty()){
            StationDeviceEquipment eleMeter = new StationDeviceEquipment();
            eleMeter.setType("elecMeter");
            eleMeter.setName("电表");
            equipments.add(eleMeter);
        }
        //3气象仪
        deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(stationId);
        deviceReqVO.setDeviceType(DeviceTypeConstant.WEATHER_STATION);
        List<DeviceRespVO> weatherStations = deviceService.getList(deviceReqVO);
        if(!weatherStations.isEmpty()){
            StationDeviceEquipment weatherStation = new StationDeviceEquipment();
            weatherStation.setType("weatherInstrument");
            weatherStation.setName("气象仪");
            equipments.add(weatherStation);
        }
        pvPanel.setEquipments(equipments);
        return DataResult.success(pvPanel);
    }


    @PostMapping("/realtimeCurve")
    @ApiOperation(value = "实时曲线")
    @Cacheable(cacheManager = "thirtySecondCacheManager", value = "realtimeCurve", key = "#stationReq.stationId", sync = true)
    public DataResult<List<RealtimeCurveRespVO>> realtimeCurve(@RequestBody StationReq stationReq) {
        //查电站下逆变器
        log.info("getIntervalsByStationId start:" + System.currentTimeMillis());
        List<DeviceRespVO> deviceRespVOS = pvStationService.getIntervalsByStationId(stationReq.getStationId());
        log.info("getIntervalsByStationId end:" + System.currentTimeMillis());
        List<RealtimeCurveRespVO> resList = pvStationService.getRealtimeCurve(stationReq.getStationId(), deviceRespVOS);
        log.info("getRealtimeCurve end:" + System.currentTimeMillis());
        //返回值的BigDecimal类型保留两位小数
        for (RealtimeCurveRespVO realtimeCurveRespVO : resList) {
            bigDecimalUtil.keepTwoDecimalPlaces(realtimeCurveRespVO);
            bigDecimalUtil.ifIsNUll(realtimeCurveRespVO);
        }
        return DataResult.success(resList);
    }


    @PostMapping("/powerGenerationCurve")
    @ApiOperation(value = "发电量和收益曲线")
    public DataResult<List<PowerGenerateRespVO>> powerGenerationCurve(@RequestBody StationCurveReq stationCurveReq) {
        //使用redis缓存
        String key = RedisKeyConstant.PV.POWER_GENERATION_CURVE + stationCurveReq.getStationId() + ":" + stationCurveReq.getType();
        if (redisService.hasKey(key)) {
            log.info("发电量和收益曲线:stationId:{},type:{}, 本次走Redis缓存", stationCurveReq.getStationId(), stationCurveReq.getType());
            List<PowerGenerateRespVO> generateRespVOList = (List<PowerGenerateRespVO>) redisService.get(key);
            return DataResult.success(generateRespVOList);
        }
        //判断电站是否为空，由于admin的账户不传电站id
        if (stationCurveReq.getStationId() == null) {
            return DataResult.success(new ArrayList<>());
        }
        //日发电量 月发电量 年发电量
        //日发电量和收益 按小时 ,从时序库查询
        //不管哪个类型,都要查电站下逆变器
        List<DeviceRespVO> deviceRespVOS = pvStationService.getIntervalsByStationId(stationCurveReq.getStationId());
        if (deviceRespVOS.isEmpty()) {
            return DataResult.success(new ArrayList<>());
        }
        List<PowerGenerateRespVO> powerGenerates = new ArrayList<>();
        //时间类型
        String queryType = stationCurveReq.getType();
        Date today = new Date();
        //如果类型是日 查当日的
        if (CommonConstant.DAY.equals(queryType)) {
            powerGenerates = pvStationService.powerGenerationCurrentDay(stationCurveReq.getStationId(), deviceRespVOS, today);
        }
        //当月 和当年的
        if (CommonConstant.MONTH.equals(queryType) || CommonConstant.YEAR.equals(queryType)) {
            powerGenerates = pvStationService.powerGeneration(stationCurveReq.getStationId(), deviceRespVOS, queryType);
        }
        //返回值的BigDecimal类型保留两位小数
        for (PowerGenerateRespVO powerGenerate : powerGenerates) {
            bigDecimalUtil.keepTwoDecimalPlaces(powerGenerate);
            bigDecimalUtil.ifIsNUll(powerGenerate);
        }
        //保存缓存
        redisService.set(key, powerGenerates, 2, TimeUnit.MINUTES);
        return DataResult.success(powerGenerates);
    }

    @PostMapping("/inverterList")
    @ApiOperation(value = "逆变器列表")
    @Cacheable(cacheManager = "tenSecondCacheManager", value = "inverterList", key = "#stationReq.stationId", sync = true)
    public DataResult<List<InverterRespVO>> inverterList(@RequestBody StationReq stationReq) {
        List<InverterRespVO> list = pvStationService.inverterStatusList(stationReq);
        for (InverterRespVO inverterRespVO : list) {
            bigDecimalUtil.keepTwoDecimalPlaces(inverterRespVO);
            bigDecimalUtil.ifIsNUll(inverterRespVO);
        }
        return DataResult.success(list);
    }

    @PostMapping("/forStationCockpit")
    @ApiOperation(value = "给电站用的大屏数据")
    public DataResult<CockForStationResp> forStationCockpit(HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByToken(token);
        Integer groupId = user.getGroupId();
        //使用redis缓存
        String key = RedisKeyConstant.COCKPIT.FOR_STATION_COCKPIT + groupId;
        if (redisService.hasKey(key)) {
            log.info("给电站用的大屏数据:groupId:{}, 本次走Redis缓存", groupId);
            CockForStationResp stationCockpitValue = (CockForStationResp) redisService.get(key);
            return DataResult.success(stationCockpitValue);
        }
        CockForStationResp stationCockpitValue = stationService.getStationCockpitValue(user);
        bigDecimalUtil.ifIsNUll(stationCockpitValue);
        bigDecimalUtil.keepTwoDecimalPlaces(stationCockpitValue);
        //保存缓存
        redisService.set(key, stationCockpitValue, 5, TimeUnit.MINUTES);
        return DataResult.success(stationCockpitValue);
    }


    @PostMapping("/commonElemeterList")
    @ApiOperation(value = "通用电表列表")
    public DataResult<List<CommonElemeterResp>> commonElemeterList(@RequestBody @Valid StationReq stationReq) {
        Integer stationId = stationReq.getStationId();
        Station station = stationService.selectById(stationId);
        String address = station.getAddress();
        //结果集
        List<CommonElemeterResp> list = new ArrayList<>();
        //查询站下所有通用电表
        DeviceReqVO deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(stationId);
        //设备为通用电表
        deviceReqVO.setDeviceType(DeviceTypeConstant.COMMON_ELEMETER);
        List<DeviceRespVO> deviceList = deviceService.getList(deviceReqVO);
        for (DeviceRespVO deviceRespVO : deviceList) {
            //使用redis缓存
            String key = RedisKeyConstant.COMMON_ELEMETER + stationId + ":" + deviceRespVO.getSrcId();
            if (redisService.hasKey(key)) {
                log.info("通用电表数据: srcId:{}", deviceRespVO.getSrcId());
                Object o = redisService.hgetall(key);
                HashMap<String, Object> map = (HashMap) o;
                ElemeterOrig elemeterOrig = JSON.parseObject(JSON.toJSONString(map), ElemeterOrig.class);
                CommonElemeterResp elemeter = new CommonElemeterResp();
                //将点表数据扔到对象中
                elemeter.setForwardActE0(elemeterOrig.getForwardActE0() == null ? BigDecimal.ZERO : elemeterOrig.getForwardActE0().getValue());
                elemeter.setForwardActE1(elemeterOrig.getForwardActE1() == null ? BigDecimal.ZERO : elemeterOrig.getForwardActE1().getValue());
                elemeter.setForwardActE2(elemeterOrig.getForwardActE2() == null ? BigDecimal.ZERO : elemeterOrig.getForwardActE2().getValue());
                elemeter.setForwardActE3(elemeterOrig.getForwardActE3() == null ? BigDecimal.ZERO : elemeterOrig.getForwardActE3().getValue());
                elemeter.setForwardActE4(elemeterOrig.getForwardActE4() == null ? BigDecimal.ZERO : elemeterOrig.getForwardActE4().getValue());

                elemeter.setBackwardActE0(elemeterOrig.getBackwardActE0() == null ? BigDecimal.ZERO : elemeterOrig.getBackwardActE0().getValue());
                elemeter.setBackwardActE1(elemeterOrig.getBackwardActE1() == null ? BigDecimal.ZERO : elemeterOrig.getBackwardActE1().getValue());
                elemeter.setBackwardActE2(elemeterOrig.getBackwardActE2() == null ? BigDecimal.ZERO : elemeterOrig.getBackwardActE2().getValue());
                elemeter.setBackwardActE3(elemeterOrig.getBackwardActE3() == null ? BigDecimal.ZERO : elemeterOrig.getBackwardActE3().getValue());
                elemeter.setBackwardActE4(elemeterOrig.getBackwardActE4() == null ? BigDecimal.ZERO : elemeterOrig.getBackwardActE4().getValue());

                bigDecimalUtil.keepTwoDecimalPlaces(elemeter);
                //通讯
                Device deviceReq = new Device();
                deviceReq.setDeviceType(deviceRespVO.getDeviceType());
                deviceReq.setStationId(stationId);
                deviceReq.setSrcId(deviceRespVO.getSrcId());
                deviceReq.setSerialNo(deviceRespVO.getSerialNo());
                boolean onLine = deviceService.isOnLine(deviceReq);
                if (onLine) {
                    elemeter.setCommunicationStatus(1);
                } else {
                    elemeter.setCommunicationStatus(0);
                }
                elemeter.setStationId(stationId);
                elemeter.setSrcId(deviceRespVO.getSrcId());
                elemeter.setDeviceName(deviceRespVO.getDeviceName());
                elemeter.setDeviceType(deviceRespVO.getDeviceType());
                JSONObject deviceJson = deviceRespVO.getDeviceJson();
                String deviceAddress = "";
                String deviceModel = "";
                if (null != deviceJson) {
                    deviceAddress = deviceJson.getString(DeviceTypeConstant.ADDRESS);
                    deviceModel = deviceJson.getString(DeviceTypeConstant.DEVICE_MODEL);
                }
                deviceAddress = (null == deviceAddress ? "" : deviceAddress);
                elemeter.setAddress(address + deviceAddress);
                elemeter.setDeviceModel(deviceModel);
                list.add(elemeter);
            }
        }

        return DataResult.success(list);
    }

    @PostMapping("/weatherStationList")
    @ApiOperation(value = "气象仪列表")
    public DataResult<List<WeatherStationResp>> weatherStationList(@RequestBody @Valid StationReq stationReq) {
        Integer stationId = stationReq.getStationId();
        Station station = stationService.selectById(stationId);
        String address = station.getAddress();
        //结果集
        List<WeatherStationResp> list = new ArrayList<>();
        //查询站下所有通用电表
        DeviceReqVO deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(stationId);
        //设备为气象仪
        deviceReqVO.setDeviceType(DeviceTypeConstant.WEATHER_STATION);
        List<DeviceRespVO> deviceList = deviceService.getList(deviceReqVO);
        for (DeviceRespVO deviceRespVO : deviceList) {
            //使用redis缓存
            String key = RedisKeyConstant.WEATHER_STATION + stationId + ":" + deviceRespVO.getSrcId();
            if (redisService.hasKey(key)) {
                log.info("气象仪数据: srcId:{}", deviceRespVO.getSrcId());
                Object o = redisService.hgetall(key);
                HashMap<String, Object> map = (HashMap) o;
                WeatherStationOrig weatherStationOrig = JSON.parseObject(JSON.toJSONString(map), WeatherStationOrig.class);
                WeatherStationResp weatherStation = new WeatherStationResp();
                //取那几个点表值
                weatherStation.setWindSpeed(weatherStationOrig.getVelocity() == null ? BigDecimal.ZERO : weatherStationOrig.getVelocity().getValue());
                weatherStation.setRainfall(weatherStationOrig.getPrecipitation() == null ? BigDecimal.ZERO : weatherStationOrig.getPrecipitation().getValue());
                weatherStation.setTemperature(weatherStationOrig.getTemperature() == null ? BigDecimal.ZERO : weatherStationOrig.getTemperature().getValue());
                weatherStation.setPressure(weatherStationOrig.getBarometric() == null ? BigDecimal.ZERO : weatherStationOrig.getBarometric().getValue());
                weatherStation.setRadiation(weatherStationOrig.getRadiation() == null ? BigDecimal.ZERO : weatherStationOrig.getRadiation().getValue());
                weatherStation.setWindDirection(weatherStationOrig.getWind() == null ? BigDecimal.ZERO : weatherStationOrig.getWind().getValue());
                weatherStation.setHumidity(weatherStationOrig.getHumidity() == null ? BigDecimal.ZERO : weatherStationOrig.getHumidity().getValue());
                bigDecimalUtil.keepTwoDecimalPlaces(weatherStation);
                //判断是否在线
                Device deviceReq = new Device();
                deviceReq.setDeviceType(deviceRespVO.getDeviceType());
                deviceReq.setStationId(stationId);
                deviceReq.setSrcId(deviceRespVO.getSrcId());
                deviceReq.setSerialNo(deviceRespVO.getSerialNo());
                boolean onLine = deviceService.isOnLine(deviceReq);
                if (onLine) {
                    weatherStation.setCommunicationStatus(1);
                } else {
                    weatherStation.setCommunicationStatus(0);
                }
                weatherStation.setStationId(stationId);
                weatherStation.setSrcId(deviceRespVO.getSrcId());
                weatherStation.setDeviceName(deviceRespVO.getDeviceName());
                weatherStation.setDeviceType(deviceRespVO.getDeviceType());
                JSONObject deviceJson = deviceRespVO.getDeviceJson();
                String deviceAddress = "";
                String deviceModel = "";
                if (null != deviceJson) {
                    deviceAddress = deviceJson.getString(DeviceTypeConstant.ADDRESS);
                    deviceModel = deviceJson.getString(DeviceTypeConstant.DEVICE_MODEL);
                }
                deviceAddress = (null == deviceAddress ? "" : deviceAddress);
                weatherStation.setAddress(address + deviceAddress);
                weatherStation.setDeviceModel(deviceModel);
                list.add(weatherStation);
            }
        }

        return DataResult.success(list);
    }


}
