package com.ho.business.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageInfo;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.*;
import com.ho.business.service.*;
import com.ho.business.vo.req.ColDetailsReqVo;
import com.ho.business.vo.req.DeviceReqVO;
import com.ho.business.vo.req.StationReq;
import com.ho.business.vo.req.device.DeviceStationReqVo;
import com.ho.business.vo.req.oneClickSequentialControl.OneClickSequentialControlQueryReq;
import com.ho.business.vo.req.point.*;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.point.*;
import com.ho.common.tools.annotation.HzPermission;
import com.ho.common.tools.annotation.LogAnnotation;
import com.ho.common.tools.constant.*;
import com.ho.common.tools.entity.PointCurveSrcCol;
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.*;
import com.ho.common.tools.vo.req.PointData;
import com.ho.common.tools.vo.req.StationHomeRespVo;
import com.ho.common.tools.vo.req.StatisticsCurve;
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.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 javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 点表
 * Author yule
 * Date 2022/10/13 11:35
 */
@RestController
@RequestMapping(ContextConstant.BUSINESS + "point")
@Api(tags = "一体柜点表模块")
@Slf4j
public class PointDemoController {

    @Autowired
    DeviceService deviceService;

    @Autowired
    RedisService redisService;

    @Autowired
    PointDemoService pointDemoService;

    @Autowired
    ModelDeviceService modelDeviceService;

    @Autowired
    ColDetailsService colDetailsService;

    @Autowired
    BigDecimalUtil bigDecimalUtil;

    @Autowired
    StationSnService stationSnService;

    @Autowired
    DeviceTypeConfigService deviceTypeConfigService;

    @Autowired
    DeviceCallService deviceCallService;

    @ApiOperation(value = "一体柜设备下拉列表,不分页")
    @PostMapping("findIntegratedCabinets")
    public DataResult<List<PointDeviceResp>> findIntegratedCabinets(@RequestBody DeviceStationReqVo deviceTypeReq) {
        //将数据转为PointDeviceResp对象
        List<PointDeviceResp> targetList = new ArrayList<>();
        //只查询在设备类型配置表中做配置的
        //先查设备类型
        List<String> deviceTypes = deviceTypeConfigService.getStationDeviceTypes(deviceTypeReq.getStationId());
        //设备类型配置表中没有定义,就返回空数据
        if (deviceTypes.isEmpty()) {
            log.info("设备类型表尚未配置设备类型");
            return DataResult.success(targetList);
        }
        //查设备
        DeviceReqVO deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(deviceTypeReq.getStationId());
        deviceReqVO.setDeviceTypeList(deviceTypes);
        deviceReqVO.setNeedFilter(CommonConstant.ONE);
        List<DeviceRespVO> deviceList = deviceService.getList(deviceReqVO);
        for (DeviceRespVO deviceRespVO : deviceList) {
            PointDeviceResp pointDevice = new PointDeviceResp();
            pointDevice.setStationId(deviceRespVO.getStationId());
            pointDevice.setSrcId(deviceRespVO.getSrcId());
            pointDevice.setDeviceName(deviceRespVO.getDeviceName());
            pointDevice.setDeviceType(deviceRespVO.getDeviceType());
            targetList.add(pointDevice);
        }
        return DataResult.success(targetList);
    }

    @ApiOperation(value = "树状结构设备")
    @PostMapping("treeDevices")
    public DataResult<List<DevicePointResp>> findTreeDevices(@RequestBody DeviceStationReqVo deviceTypeReq) {
        List<DeviceRespVO> deviceRespVOS = deviceCallService.selectByIdAndSrcIdNotZero(deviceTypeReq.getStationId());
        List<DevicePointResp> treeDevices = new ArrayList<>();
        if (!deviceRespVOS.isEmpty()) {
            treeDevices = deviceTypeConfigService.getTreeDevices(deviceRespVOS);
        }
        return DataResult.success(treeDevices);
    }


    @PostMapping("page")
    @ApiOperation(value = "点表列表,分页")
    public DataResult<PageResult<PointRespVO>> page(@RequestBody @Valid PointReq pointReq,HttpServletRequest request) {
        pointReq.setLang(request.getHeader(CommonConstant.LANG));
        String name = pointReq.getName();
        if (name != null) {
            name = name.trim();
            pointReq.setName(name);
        }
        List<PointRespVO> pointList = pointDemoService.getPointList(pointReq);
        //java内存分页
        PageResult pageResult = new PageResult<>();
        if (!pointList.isEmpty()) {
            List list = PageUtils.dealList(pointList, pointReq.getPageNum(), pointReq.getPageSize());
            pageResult = PageUtils.getPageResult(new PageInfo<>(list));
            pageResult.setTotalRows(pointList.size());
            pageResult.setTotalPages(pointList.size() / pointReq.getPageSize() + 1);
        } else {
            pageResult = PageUtils.getPageResult(new PageInfo<>(new ArrayList<>()));
        }
        return DataResult.success(pageResult);
    }

    @PostMapping("getPointList")
    @ApiOperation(value = "点表列表(可控点)")
    public DataResult<List<PointRespVO>> getPointList(@RequestBody @Valid PointReq pointReq) {
        String name = pointReq.getName();
        if (name != null) {
            name = name.trim();
            pointReq.setName(name);
        }
        pointReq.setIsSave(1);
        List<PointRespVO> pointList = pointDemoService.getPointList(pointReq);
        return DataResult.success(pointList);
    }

    @PostMapping("pointList")
    @ApiOperation(value = "点表列表,不分页")
    public DataResult<List<PointListRespVo>> pointList(@RequestBody @Valid PointReq pointReq,HttpServletRequest request) {
        pointReq.setLang(request.getHeader(CommonConstant.LANG));
        String name = pointReq.getName();
        if (name != null) {
            name = name.trim();
            pointReq.setName(name);
        }
        List<PointListRespVo> pointList = pointDemoService.pointList(pointReq);
        return DataResult.success(pointList);
    }

    @PostMapping("queryPoint")
    @ApiOperation(value = "根据设备查询点表")
    public DataResult<List<QueryPointRespVo>> queryPoint(@RequestBody @Valid PointVo vo,HttpServletRequest request) {
        vo.setLang(request.getHeader(CommonConstant.LANG));
        List<QueryPointRespVo> pointList = pointDemoService.queryPoint(vo);
        return DataResult.success(pointList);
    }

    @PostMapping("queryVirtualPoint")
    @ApiOperation(value = "根据设备查询虚拟点表")
    public DataResult<List<QueryPointRespVo>> queryVirtualPoint(@RequestBody @Valid PointVo vo,HttpServletRequest request) {
        vo.setLang(request.getHeader(CommonConstant.LANG));
        List<QueryPointRespVo> pointList = pointDemoService.queryVirtualPoint(vo);
        return DataResult.success(pointList);
    }

    @PostMapping("queryControlPoint")
    @ApiOperation(value = "查询可配置顺控点")
    public DataResult<List<PointRespVO>> queryControlPoint(@RequestBody @Valid OneClickSequentialControlQueryReq vo) {
        List<PointRespVO> pointList = pointDemoService.queryControlPoint(vo);
        return DataResult.success(pointList);
    }

    @PostMapping("updateOne")
    @ApiOperation(value = "更新数据")
    @LogAnnotation(title = "一体柜点表模块", action = "更新数据")
    //@HzPermission(value = PermissionConstant.REMOTECONTROL_COMMAND_SINGLEREFRESH)
    public DataResult<PointRespVO> updateOne(@RequestBody @Valid PointOneReq pointReq) {
        PointRespVO point = pointDemoService.getPointRespVO(pointReq);
        return DataResult.success(point);
    }


    @PostMapping("getSN")
    @ApiIgnore
    @ApiOperation(value = "获取电站下面所有的sn")
    public DataResult<List<StationSn>> getSN(@RequestBody @Valid PointReqVO pointReq) {
        //根据每一个设备从缓存中拿数据
        List<StationSn> stationSnList = stationSnService.getSnListByStationId(pointReq.getStationId());
        return DataResult.success(stationSnList);
    }

    @PostMapping("getDeviceSN")
    @ApiOperation(value = "获取对应设备下面的sn")
    public DataResult<List<DeviceRespVO>> getDeviceSN(@RequestBody @Valid PointReqVO pointReq) {
        //根据每一个设备从缓存中拿数据
        DeviceReqVO deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(pointReq.getStationId());
        deviceReqVO.setSrcId(pointReq.getSrcId());
        List<DeviceRespVO> deviceList = deviceService.getList(deviceReqVO);
        return DataResult.success(deviceList);
    }

    @ApiIgnore
    @PostMapping("device")
    public int Devices(@RequestBody Device device) {
        int i = deviceService.insertSelective(device);
        return i;
    }

    /**
     * 导出点表数据
     *
     * @param response
     */
    @PostMapping("/exportExcel")
    @LogAnnotation(title = "一体柜点表模块", action = "导出点表数据")
    //@HzPermission(value = {PermissionConstant.REMOTECONTROL_COMMAND_EXPORT,PermissionConstant.DATA_SHOW_EXPORT,PermissionConstant.REMOTECONTROL_COMMAND_EXPORT})
    public void exportExcel(@RequestBody @Valid PointReq pointReq, HttpServletResponse response,HttpServletRequest request) {
        String lang = request.getHeader(CommonConstant.LANG);
        pointReq.setLang(lang);
        List<PointRespVO> pointList = pointDemoService.getPointList(pointReq);

        String fileName = "点表";
        String sheetName = "数据";
        try {
            if(CommonConstant.langTemp.EN_US.equals(lang)){
                fileName = "point table";sheetName = "data";
                EasyExcelUtil.writeExcel(response, pointList, fileName, sheetName, PointRespEnVO.class);
            }else if(CommonConstant.langTemp.FR_FR.equals(lang)){
                fileName = "Tableau des points";sheetName = "données";
                EasyExcelUtil.writeExcel(response, pointList, fileName, sheetName, PointRespFraVO.class);
            }else if(CommonConstant.langTemp.ES_ES.equals(lang)){
                fileName = "Tabla de puntos";sheetName = "datos";
                EasyExcelUtil.writeExcel(response, pointList, fileName, sheetName, PointRespSpaVO.class);
            }else if(CommonConstant.langTemp.DE_DE.equals(lang)){
                fileName = "Punkttabellen";sheetName = "Daten";
                EasyExcelUtil.writeExcel(response, pointList, fileName, sheetName, PointRespDeVO.class);
            }else if(CommonConstant.langTemp.PL_PL.equals(lang)){
                fileName = "Tabela punktowa";sheetName = "Dane";
                EasyExcelUtil.writeExcel(response, pointList, fileName, sheetName, PointRespPlVO.class);
            }else if(CommonConstant.langTemp.AR_EG.equals(lang)){
                fileName = "نقطة الجدول";sheetName = "داتا";
                EasyExcelUtil.writeExcel(response, pointList, fileName, sheetName, PointRespAraVO.class);
            }else{
                EasyExcelUtil.writeExcel(response, pointList, fileName, sheetName, PointRespVO.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 导出历史数据
     *
     * @param response
     */
    @PostMapping("/hisExportExcel")
    @LogAnnotation(title = "一体柜点表模块", action = "导出历史数据")
    @HzPermission(PermissionConstant.DATA_HISCURVE_EXPORT)
    public void hisExportExcel(@RequestBody @Valid PointCurveReq pointCurveReq, HttpServletResponse response, HttpServletRequest request) {
        pointCurveReq.setLang(request.getHeader(CommonConstant.LANG));
        pointDemoService.getHisExportExcel(pointCurveReq, response);
    }

    @PostMapping("pointCurve")
    @ApiOperation(value = "点表曲线")
    public DataResult<List<PointCurveResp>> pointCurve(@RequestBody @Valid PointCurveReq pointCurveReq, HttpServletRequest request) {
        pointCurveReq.setLang(request.getHeader(CommonConstant.LANG));
        List<PointCurveResp> pointCurveRespList = new ArrayList<>();
        //对开始结束时间进行处理 （对bug129）
        if (pointCurveReq.getBeginTime() != null) {
            pointCurveReq.setBeginTime(pointCurveReq.getBeginTime().substring(0, pointCurveReq.getBeginTime().length() - 1) + "1");
        }
        if (pointCurveReq.getEndTime() != null) {
            pointCurveReq.setEndTime(pointCurveReq.getEndTime().substring(0, pointCurveReq.getEndTime().length() - 1) + "1");
        }
        //对传输过来的col集合进行判断是否大于10个
        if (pointCurveReq.getDeviceIdList() != null && pointCurveReq.getDeviceIdList().size() < 50) {
            pointCurveRespList = pointDemoService.getPointCurve(pointCurveReq);
        }
        for (PointCurveResp pointCurveResp : pointCurveRespList) {
            List<StatisticsCurve> staticCurveList = pointCurveResp.getStaticCurveList();
            for (StatisticsCurve statisticsRespVO : staticCurveList) {
                if (null != statisticsRespVO.getDigital()) {
                    statisticsRespVO.setDigital(NumberUtil.round(statisticsRespVO.getDigital(), 2).doubleValue());
                }
            }
            if (pointCurveReq.getIsStrategy() != null && pointCurveReq.getIsStrategy() == 1) {
                if (!staticCurveList.isEmpty() && staticCurveList.size() < 1440) {
                    int count = 1440 - staticCurveList.size();
                    String date = staticCurveList.get(staticCurveList.size() - 1).getDate();
                    for (int i = 0; i < count; i++) {
                        StatisticsCurve statisticsCurve = new StatisticsCurve();
                        statisticsCurve.setDigital(null);
                        DateTime offset = DateUtil.offset(DateUtil.parse(date, CommonConstant.DATE), DateField.MINUTE, i + 1);
                        statisticsCurve.setDate(DateUtil.format(offset, CommonConstant.DATE));
                        staticCurveList.add(statisticsCurve);
                    }
                }
            }
        }
        //判断是否为策略总览页面查询
        if (pointCurveReq.getIsStrategy() != null && pointCurveReq.getIsStrategy() == 1) {
            PointCurveResp pointCurveResp = pointDemoService.getPlanCurve(pointCurveReq.getStationId());
            if (pointCurveResp != null) {
                pointCurveRespList.add(pointCurveResp);
            }
        }
        int size = pointCurveRespList.size();
        pointCurveRespList = pointCurveRespList.stream().sorted((x, y) -> {
            if (x.getSrcId() == null || y.getSrcId() == null) {
                return size;
            } else {
                return x.getSrcId() - y.getSrcId();
            }

        }).collect(Collectors.toList());
        return DataResult.success(pointCurveRespList);
    }

    @PostMapping("pointDataShow")
    @ApiOperation(value = "点表数据展示")
    public DataResult<PageResult<List<Object>>> pointDataShow(@RequestBody @Valid PointCurveReq pointCurveReq) {
        PageResult<List<Object>> pointCurveRespList = PageUtils.getPageResult(new PageInfo<>(new ArrayList<>()));
        //对传输过来的col集合进行判断是否大于10个
        if (pointCurveReq.getDeviceIdList().size() < 50) {
            pointCurveRespList = pointDemoService.pointDataShow(pointCurveReq);
        }
        return DataResult.success(pointCurveRespList);
    }

    @PostMapping("pointDataShowList")
    @ApiOperation(value = "点表真实数据展示(每个点位分开)")
    public DataResult<List<PageResult>> pointDataShowList(@RequestBody @Valid PointCurveReq pointCurveReq, HttpServletRequest request) {
        pointCurveReq.setLang(request.getHeader(CommonConstant.LANG));
        List<PageResult> pointCurveRespList = new ArrayList<>();
        //对传输过来的col集合进行判断是否大于10个
        if (pointCurveReq.getDeviceIdList().size() < 50) {
            pointCurveRespList = pointDemoService.pointDataShowList(pointCurveReq);
        }
        return DataResult.success(pointCurveRespList);
    }

    @PostMapping("colHistoricalDetails")
    @ApiOperation(value = "点表col字段历史数据展示")
    public DataResult<List<PointData>> colHistoricalDetails(@RequestBody @Valid ColDetailsReqVo colDetailsReqVo) {
        List<PointData> list = colDetailsService.getColCurve(colDetailsReqVo);
        for (PointData pointData : list) {
            bigDecimalUtil.keepTwoDecimalPlaces(pointData);
            bigDecimalUtil.ifIsNUll(pointData);
        }
        return DataResult.success(list);
    }

    @PostMapping("colHistoricalList")
    @ApiOperation(value = "点表col字段历史数据列表展示")
    public DataResult<PageResult<StationHomeRespVo>> colHistoricalList(@RequestBody @Valid ColDetailsReqVo colDetailsReqVo) {
        PageResult<StationHomeRespVo> list = new PageResult<>();
        list = colDetailsService.getColList(colDetailsReqVo);
        if (list.getList() != null) {
            for (StationHomeRespVo stationHomeRespVo : list.getList()) {
                bigDecimalUtil.keepTwoDecimalPlaces(stationHomeRespVo);
                bigDecimalUtil.ifIsNUll(stationHomeRespVo);
            }
        }
        list.setList(list.getList());
        return DataResult.success(list);
    }

    @PostMapping("beforeQueryPoint")
    @ApiOperation(value = "默认查点表的输入条件查询")
    public DataResult<BeforeQueryPointResp> beforeQueryPoint(@RequestBody @Valid StationReq stationReq) {
        Integer stationId = stationReq.getStationId();
        BeforeQueryPointResp beforeQueryPointResp = new BeforeQueryPointResp();
        //先查询第一个PCS设备
        List<DeviceRespVO> listByDeviceType = deviceService.getListByDeviceType(stationId, DeviceTypeConstant.PCS);
        beforeQueryPointResp.setHasPcs(false);
        if (listByDeviceType.isEmpty()) {
            return DataResult.success(beforeQueryPointResp);
        }
        DeviceRespVO device = listByDeviceType.get(0);
        beforeQueryPointResp.setSrcId(device.getSrcId());

        //9个指标,得转换为映射的deviceCol
        List<String> cols = Arrays.asList("activeAPower", "activeBPower", "activeCPower",
                "currentA", "currentB", "currentC",
                "volA", "volB", "volC");
        List<String> refCols = new ArrayList<>();
        for (String col : cols) {
            String deviceCol = getDeviceCol(device.getDeviceType(), col);
            if (deviceCol != null) {
                refCols.add(deviceCol);
            }
        }
        if (!refCols.isEmpty()) {
            beforeQueryPointResp.setHasPcs(true);
        }
        beforeQueryPointResp.setCols(refCols);
        //默认生成一个昨天到今天的时间跨度
        Date now = new Date();
        DateTime dateTime = DateUtil.offsetDay(now, -1);
        String beginTime = DateUtil.format(dateTime, CommonConstant.DATE);
        String endTime = DateUtil.format(now, CommonConstant.DATE);

        beforeQueryPointResp.setBeginTime(beginTime);
        beforeQueryPointResp.setEndTime(endTime);
        return DataResult.success(beforeQueryPointResp);
    }

    @ApiOperation(value = "返回一个存在点表的设备id(命令下发界面专用)")
    @PostMapping("beforeOrderSend")
    public DataResult<BeforeSendOrderResp> beforeOrderSend(@RequestBody StationReq stationReq) {
        BeforeSendOrderResp beforeSendOrderResp = deviceService.beforeOrderSend(stationReq);
        return DataResult.success(beforeSendOrderResp);
    }

    //字段映射
    private String getDeviceCol(String deviceType, String modelCol) {
        String colReflex = null;
        List<ModelDeviceColComp> cIaCompList = modelDeviceService.getCompListByType("device", deviceType, modelCol);
        if (!cIaCompList.isEmpty()) {
            ModelDeviceColComp cIaModelDeviceCol = cIaCompList.get(0);
            String deviceCol = cIaModelDeviceCol.getDeviceCol();
            log.info("deviceCol:" + deviceCol);
            colReflex = deviceCol;
        }
        return colReflex;
    }

    @PostMapping("getPointCurve")
    @ApiOperation(value = "首页根据映射值获取曲线(app界面使用)")
    public DataResult<List<PointCurveResp>> getPointCurve(@RequestBody HomePageReqVo vo, HttpServletRequest request) {
        PointCurveReq pointCurveReq = pointDemoService.getPointCurveReq(vo);
        List<PointCurveResp> pointCurveRespList = pointCurve(pointCurveReq,request).getData();
        List<PointCurveSrcCol> deviceIdList = pointCurveReq.getDeviceIdList();
        if (!deviceIdList.isEmpty()) {
            Map<String, BigDecimal> map = deviceIdList.get(0).getMap();
            if (map != null) {
                BigDecimal factor;
                for (PointCurveResp p : pointCurveRespList) {
                    factor = map.get(p.getCol());
                    if (null != factor) {
                        List<StatisticsCurve> staticCurveList = p.getStaticCurveList();
                        for (StatisticsCurve curve : staticCurveList) {
                            if (curve.getDigital() != null) {
                                curve.setDigital(new BigDecimal(curve.getDigital()).multiply(factor).doubleValue());
                            }
                        }
                    }
                }
            }
        }
        return DataResult.success(pointCurveRespList);
    }

    @Autowired
    UserHabitService userHabitService;

    @PostMapping("addUserHabit")
    @ApiOperation(value = "增加用户习惯")
    public DataResult addUserHabit(@RequestBody UserHabitReqVo vo, HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByToken(token);
        UserHabit userHabit = new UserHabit();
        userHabit.setUserId(user.getUserId());
        userHabit.setUserData(vo.getDeviceJson().toJSONString());
        userHabitService.insertUserHabit(userHabit);
        return DataResult.success();
    }

    @PostMapping("updateUserHabit")
    @ApiOperation(value = "更新用户习惯")
    public DataResult updateUserHabit(@RequestBody UserHabitReqVo vo) {
        UserHabit userHabit = new UserHabit();
        userHabit.setId(vo.getId());
        userHabit.setUserData(vo.getDeviceJson().toString());
        userHabitService.updateById(userHabit);
        return DataResult.success();
    }

    @PostMapping("queryUserHabit")
    @ApiOperation(value = "查询用户习惯")
    public DataResult<UserHabitRespVo> queryUserHabit(HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser user = redisService.getSimpleUserByToken(token);
        UserHabit userHabit = userHabitService.selectByUserId(user.getUserId());
        UserHabitRespVo userHabitRespVo = null;
        if (null != userHabit) {
            userHabitRespVo = new UserHabitRespVo();
            String userData = userHabit.getUserData();
            JSONArray objects = JSONArray.parseArray(userData);
            userHabitRespVo.setDeviceJson(objects);
            userHabitRespVo.setId(userHabit.getId());
        }
        return DataResult.success(userHabitRespVo);
    }

    @PostMapping("modifyHistoryData")
    @ApiOperation(value = "更改历史值")
    @HzPermission(PermissionConstant.MODIFY_HISTORY_DATA)
    public DataResult modifyHistoryData(@RequestBody PointCurveReq pointCurveReq) {
        pointDemoService.modifyHistoryData(pointCurveReq);
        return DataResult.success();
    }
}
