package com.ho.business.controller;

import com.ho.business.common.BusiTool;
import com.ho.business.entity.Station;
import com.ho.business.feignclient.FileCenterFeignClient;
import com.ho.business.service.CockpitService;
import com.ho.business.service.StationService;
import com.ho.business.vo.req.cockpit.CockpitReqVO;
import com.ho.business.vo.resp.StationRespVO;
import com.ho.business.vo.resp.cockpit.*;
import com.ho.common.tools.annotation.LargeScreenToken;
import com.ho.common.tools.annotation.TokenIgnore;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.ContextConstant;
import com.ho.common.tools.constant.EnvConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.entity.WeatherRespVo;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.BigDecimalUtil;
import com.ho.common.tools.util.IPUtils;
import com.ho.common.tools.vo.req.WeatherReq;
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.beans.factory.annotation.Value;
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 springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Description 驾驶舱
 * Author yule
 * Date 2023/1/10 15:47
 */
@RestController
@RequestMapping(ContextConstant.BUSINESS + "cockpit")
@Api(tags = "驾驶舱")
@Slf4j
public class CockpitController {

    @Autowired
    RedisService redisService;

    @Autowired
    CockpitService cockpitService;

    @Autowired
    BigDecimalUtil bigDecimalUtil;


    @Autowired
    StationService stationService;

    @Autowired
    FileCenterFeignClient fileCenterFeignClient;

    @Autowired
    BusiTool busiTool;

    @Value("${spring.profiles.active}")
    String env;

    @Value("${event.currentMaxDay}")
    Integer currentMaxDay;

    @Value("${event.bigScreenEventLimit}")
    Integer bigScreenEventLimit;

    @PostMapping("/testBigToken")
    @ApiOperation(value = "测试使用大屏token访问接口")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<StationSummaryRespVO> bigScreen(HttpServletRequest request) {

        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        Integer groupId = user.getGroupId();
        return DataResult.success();
    }

    @PostMapping("/summary")
    @ApiOperation(value = "电站概述")
    @ApiIgnore
    @TokenIgnore
    @LargeScreenToken
    public DataResult<StationSummaryRespVO> summary(HttpServletRequest request) {

        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        StationSummaryRespVO respVO = cockpitService.getSummary(user);
        bigDecimalUtil.keepTwoDecimalPlaces(respVO);
        bigDecimalUtil.ifIsNUll(respVO);
        return DataResult.success(respVO);
    }

    @PostMapping("/revenueStatistics")
    @ApiOperation(value = "收益统计")
    @TokenIgnore
    @ApiIgnore
    @LargeScreenToken
    public DataResult<List<RevenueStatisticsRespVO>> revenueStatistics(HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        List<RevenueStatisticsRespVO> respVO = cockpitService.getRevenueStatistics(user);
        for (RevenueStatisticsRespVO revenueStatisticsRespVO : respVO) {
            bigDecimalUtil.keepTwoDecimalPlaces(revenueStatisticsRespVO);
            bigDecimalUtil.ifIsNUll(revenueStatisticsRespVO);
        }
        return DataResult.success(respVO);
    }

    @PostMapping("/revenueStatisticsJob")
    @ApiOperation(value = "收益统计定时任务")
    @TokenIgnore
    @ApiIgnore
    public DataResult<List<RevenueStatisticsRespVO>> revenueStatisticsJob() {
        cockpitService.getRevenueStatistics();
        return DataResult.success();
    }

    @PostMapping("/totalPowerGeneration")
    @ApiOperation(value = "总发电量")
    @TokenIgnore
    @ApiIgnore
    @LargeScreenToken
    public DataResult<List<TotalPowerGenerationRespVO>> totalPowerGeneration(@RequestBody CockpitReqVO vo, HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        List<TotalPowerGenerationRespVO> respVO = cockpitService.getTotalPowerGenerations(vo, user);
        for (TotalPowerGenerationRespVO totalPowerGenerationRespVO : respVO) {
            bigDecimalUtil.keepTwoDecimalPlaces(totalPowerGenerationRespVO);
            bigDecimalUtil.ifIsNUll(totalPowerGenerationRespVO);
        }
        return DataResult.success(respVO);
    }

    @PostMapping("/proportionOfPowerGeneration")
    @ApiOperation(value = "发电占比")
    @TokenIgnore
    @ApiIgnore
    @LargeScreenToken
    public DataResult<List<ProportionOfPowerRespVO>> proportionOfPowerGeneration(HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        List<ProportionOfPowerRespVO> respVO = cockpitService.getProportionOfPowerGeneration(user);
        for (ProportionOfPowerRespVO proportionOfPowerRespVO : respVO) {
            bigDecimalUtil.keepTwoDecimalPlaces(proportionOfPowerRespVO);
            bigDecimalUtil.ifIsNUll(proportionOfPowerRespVO);
        }
        return DataResult.success(respVO);
    }

    @PostMapping("/revenueRanking")
    @ApiOperation(value = "收益排行")
    @TokenIgnore
    @ApiIgnore
    @LargeScreenToken
    public DataResult<List<RevenueRespVO>> revenueRanking(HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        List<RevenueRespVO> respVO = cockpitService.getRevenueRanking(user);
        for (RevenueRespVO revenueRespVO : respVO) {
            bigDecimalUtil.keepTwoDecimalPlaces(revenueRespVO);
            bigDecimalUtil.ifIsNUll(revenueRespVO);
        }
        return DataResult.success(respVO);
    }

    @PostMapping("/weather")
    @ApiOperation(value = "大屏天气接口")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<WeatherRespVo> weather(HttpServletRequest request) {
        String ipAddr = IPUtils.getIpAddr(request);
        log.info("获取到IP: {}", ipAddr);
        if (env.equals("dev") || env.equals("exp")) {
            ipAddr = "114.222.185.168";
        }
        //通合的先显示南通的地址IP,后续再优化
        else if(EnvConstant.TONG_HE.equals(env)){
            ipAddr = "221.227.154.59";
        }
        //调用file-center的天气接口
        WeatherReq weatherReq = new WeatherReq();
        weatherReq.setIp(ipAddr);
        DataResult<WeatherRespVo> weatherResult = fileCenterFeignClient.queryWeather(weatherReq);
        log.info("天气接口数据:" + weatherResult);
        return DataResult.success(weatherResult.getData());
    }

    @PostMapping("/groupData")
    @ApiOperation(value = "集团数据")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<GroupDataRespVo> groupData(HttpServletRequest request){
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        //
        Integer groupId = user.getGroupId();
        String key = RedisKeyConstant.COCKPIT.GROUP_DATA + groupId;
        if(redisService.hasKey(key)){
            log.info("大屏集团数据走redis缓存: {}", groupId);
            GroupDataRespVo groupDataRespVo = (GroupDataRespVo)redisService.get(key);
            return DataResult.success(groupDataRespVo);
        }
        GroupDataRespVo groupDataRespVo = cockpitService.getGroupData(user);
        bigDecimalUtil.keepTwoDecimalPlaces(groupDataRespVo);
        bigDecimalUtil.ifIsNUll(groupDataRespVo);
        redisService.set(key, groupDataRespVo, 2, TimeUnit.MINUTES);
        return DataResult.success(groupDataRespVo);
    }

    @PostMapping("/cumulative")
    @ApiOperation(value = "累计总和")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<CumulativeRespVO> cumulative(HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        Integer groupId = user.getGroupId();
        String key = RedisKeyConstant.COCKPIT.CUMULATIVE + groupId;
        if(redisService.hasKey(key)){
            log.info("大屏累计总和走redis缓存: {}", groupId);
            CumulativeRespVO respVO = (CumulativeRespVO)redisService.get(key);
            return DataResult.success(respVO);
        }
        CumulativeRespVO respVO = cockpitService.getCumulative(user);
        bigDecimalUtil.keepTwoDecimalPlaces(respVO);
        bigDecimalUtil.ifIsNUll(respVO);
        redisService.set(key, respVO, 6, TimeUnit.MINUTES);
        return DataResult.success(respVO);
    }

    @PostMapping("/stationMap")
    @ApiOperation(value = "电站地图")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<List<StationMapRespVO>> stationMap(HttpServletRequest request){
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        Integer groupId = user.getGroupId();
        String key = RedisKeyConstant.COCKPIT.STATION_MAP + groupId;
        if(redisService.hasKey(key)){
            log.info("大屏电站地图走redis缓存: {}", groupId);
            List<StationMapRespVO> respVO = (List<StationMapRespVO>)redisService.get(key);
            return DataResult.success(respVO);
        }
        List<StationMapRespVO> respVO = cockpitService.getStationMap(user);
        redisService.set(key, respVO, 6, TimeUnit.MINUTES);
        return DataResult.success(respVO);
    }

    @PostMapping("/conditionMonitoring")
    @ApiOperation(value = "状态监测")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<ConditionMonitoringRespVO> conditionMonitoring(HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        ConditionMonitoringRespVO respVO = cockpitService.getConditionMonitoring(user);
        bigDecimalUtil.ifIsNUll(respVO);
        return DataResult.success(respVO);
    }

    @PostMapping("/stationOperation")
    @ApiOperation(value = "电站运行数据")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<List<StationOperationRespVO>> stationOperation(HttpServletRequest request){
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        List<StationOperationRespVO> list = cockpitService.getStationOperation(user);
        for (StationOperationRespVO stationOperationRespVO : list) {
            bigDecimalUtil.keepTwoDecimalPlaces(stationOperationRespVO);
            bigDecimalUtil.ifIsNUll(stationOperationRespVO);
        }
        return DataResult.success(list);
    }


    @PostMapping("/chargeCockpitPowerGeneration")
    @ApiOperation(value = "定时修改集团数据中的储能累计放电量和充电桩累计放电量" ,hidden = true)
    @TokenIgnore
    public void chargeCockpitPowerGeneration(){
        List<Station> stations = stationService.selectAll();
        List<Integer> groupIdList = stations.stream().map(s -> {
            return s.getGroupId();
        }).distinct().collect(Collectors.toList());
        for (Integer groupId : groupIdList) {
            //储能累计放电量key
            String energyKey = RedisKeyConstant.COCKPIT.ENERGY_POWER_GENERATION +groupId;
            if (redisService.hasKey(energyKey)){
                BigDecimal energyPowerGeneration = (BigDecimal) redisService.get(energyKey);
                BigDecimal sum = energyPowerGeneration.add(CommonConstant.TongHeCockpit.DailyEnergyPowerGeneration.divide(new BigDecimal(24),4,BigDecimal.ROUND_HALF_UP));
                redisService.set(energyKey,sum);
            }else {
                redisService.set(energyKey,CommonConstant.TongHeCockpit.EnergyPowerGeneration);
            }
            //充电桩累计放电量key
            String chargePileKey = RedisKeyConstant.COCKPIT.CHARGE_PILE_POWER_GENERATION + groupId;
            if (redisService.hasKey(chargePileKey)){
                BigDecimal chargePilePowerGeneration = (BigDecimal) redisService.get(chargePileKey);
                BigDecimal sum = chargePilePowerGeneration.add(CommonConstant.TongHeCockpit.DailyChargePilePowerGeneration.divide(new BigDecimal(24),4,BigDecimal.ROUND_HALF_UP));
                redisService.set(chargePileKey,sum);
            }else {
                redisService.set(chargePileKey,CommonConstant.TongHeCockpit.ChargePilePowerGeneration);
            }
        }
    }

    @PostMapping("/capacityProportion")
    @ApiOperation(value = "装机占比")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<CapacityProportionResp> capacityProportion(HttpServletRequest request){
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        CapacityProportionResp capacityProportionResp = cockpitService.capacityProportion(user);
        return DataResult.success(capacityProportionResp);
    }

    @PostMapping("/monitoringStation")
    @ApiOperation(value = "电站实时监控")
    @TokenIgnore
    @LargeScreenToken
    public DataResult<List<StationRespVO>> monitoringStation(HttpServletRequest request){
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByBigScreenToken(token);
        List<StationRespVO> list = cockpitService.monitoringStation(user);
        return DataResult.success(list);
    }
}
