package com.njcn.device.pq.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.collection.CollectionUtil;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.constant.OperateType;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.common.utils.LogUtil;
import com.njcn.device.biz.enums.DeviceResponseEnum;
import com.njcn.device.common.service.GeneralDeviceService;
import com.njcn.device.common.service.TerminalBaseService;
import com.njcn.device.line.service.LineService;
import com.njcn.device.pq.pojo.bo.DeviceType;
import com.njcn.device.pq.pojo.bo.excel.TerminalBaseExcel;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pq.pojo.dto.PreCommandDTO;
import com.njcn.device.pq.pojo.dto.PushResultDTO;
import com.njcn.device.pq.pojo.param.*;
import com.njcn.device.pq.pojo.po.Line;
import com.njcn.device.pq.pojo.vo.*;
import com.njcn.poi.util.PoiUtil;
import com.njcn.web.controller.BaseController;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * pqs
 *
 * @author cdf
 * @date 2022/1/4
 */
@Slf4j
@Api(tags = "台账管理")
@RestController
@RequestMapping("/device")
@RequiredArgsConstructor
public class TerminalBaseController extends BaseController {

    private final TerminalBaseService terminalBaseService;
    private final GeneralDeviceService generalDeviceService;
    private final LineService lineService;

    /**
     * 终端新增操作
     *
     * @author cdf
     * @date 2021/7/5
     */
    @ApiOperation("终端新增操作")
    @OperateInfo(operateType = OperateType.ADD, info = LogEnum.BUSINESS_MEDIUM)
    @PostMapping("addTerminal")
    public HttpResult<Object> addTerminal(@Valid @RequestBody AddTerminalParam addTerminalParam) {
        String methodDescribe = getMethodDescribe("addTerminal");
        //装置母线监测点相关检验
        List<String> voltageName = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(addTerminalParam.getDeviceParam())) {
            //校验装置是否存在重名
            List<DeviceParam> listDev = addTerminalParam.getDeviceParam();
            List<String> devName = listDev.stream().map(DeviceParam::getName).collect(Collectors.toList());
            long count = devName.stream().distinct().count();
            if (count != devName.size()) {
                throw new BusinessException(DeviceResponseEnum.DEVICE_REPETITION);
            }
            //校验装置是否存在重复ip
            /*List<String> devIp = listDev.stream().map(DeviceParam::getIp).collect(Collectors.toList());
            long countIp = devIp.stream().distinct().count();
            if (countIp != devIp.size()) {
                throw new BusinessException(DeviceResponseEnum.DEVICE_IP_REPETITION);
            }*/

            //校验母线名称
            for (DeviceParam deviceParam : listDev) {
                if (CollectionUtil.isNotEmpty(deviceParam.getSubVoltageParam())) {
                    List<SubVoltageParam> subvList = deviceParam.getSubVoltageParam();
                    List<String> subVName = subvList.stream().map(SubVoltageParam::getName).collect(Collectors.toList());
                    voltageName.addAll(subVName);
                    //校验监测点名称
                    for (SubVoltageParam subVoltageParam : subvList) {
                        if (CollectionUtil.isNotEmpty(subVoltageParam.getLineParam())) {
                            List<LineParam> listLine = subVoltageParam.getLineParam();
                            List<String> lineName = listLine.stream().map(LineParam::getName).collect(Collectors.toList());
                            long countLine = lineName.stream().distinct().count();
                            if (countLine != lineName.size()) {
                                throw new BusinessException(DeviceResponseEnum.LINE_NAME_REPETITION);
                            }
                            List<Integer> lineNum = listLine.stream().map(LineParam::getNum).collect(Collectors.toList());
                            long countNum = lineNum.stream().distinct().count();
                            if (countNum != lineNum.size()) {
                                throw new BusinessException(DeviceResponseEnum.LINE_NUM_REPETITION);
                            }
                        }
                    }
                }
            }

            long countSubV = voltageName.stream().distinct().count();
            if (countSubV != voltageName.size()) {
                throw new BusinessException(DeviceResponseEnum.SUBV_NAME_REPETITION);
            }
        }
        terminalBaseService.addTerminal(addTerminalParam);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }


    @ApiOperation("变电站/终端/母线/监测点同步操作")
    @OperateInfo(operateType = OperateType.ADD, info = LogEnum.BUSINESS_MEDIUM)
    @PostMapping("terminalSync")
    public HttpResult<String> terminalSync(@Valid @RequestBody SyncTerminalParam syncTerminalParam) {
        String methodDescribe = getMethodDescribe("terminalSync");
        String substation = terminalBaseService.terminalSync(syncTerminalParam);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, substation, methodDescribe);
    }


    @ApiOperation("监测点和装置同步成运行状态")
    @OperateInfo(operateType = OperateType.ADD, info = LogEnum.BUSINESS_MEDIUM)
    @GetMapping("/terminalSyncRunFly")
    public HttpResult<Boolean> terminalSyncRunFly(@RequestParam("lineId") String lineId) {
        String methodDescribe = getMethodDescribe("terminalSyncRunFly");
        Boolean b = terminalBaseService.terminalSyncRunFly(lineId);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, b, methodDescribe);
    }

    @ApiOperation("监测点信息删除")
    @OperateInfo(operateType = OperateType.ADD, info = LogEnum.BUSINESS_MEDIUM)
    @GetMapping("/terminalSyncDeleteFly")
    public HttpResult<Boolean> terminalSyncDeleteFly(@RequestParam("lineId") String lineId) {
        String methodDescribe = getMethodDescribe("terminalSyncDeleteFly");
        //获取设备id
        LineDetailDataVO lineDetailData = lineService.getLineDetailData(lineId);
        String devId =lineDetailData.getDevId();

        Boolean b = terminalBaseService.terminalSyncDeleteFly(lineId);
        //删除监测点即修改终端通知前置重启
//        terminalBaseService.askRestartDevice(devId,DeviceRebootType.LEDGER_MODIFY);

        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, b, methodDescribe);
    }

    /**
     * 终端修改操作
     *
     * @author cdf
     * @date 2021/7/19
     */
    @ApiOperation("终端修改操作")
    @OperateInfo(operateType = OperateType.UPDATE, info = LogEnum.BUSINESS_MEDIUM)
    @PutMapping("updateTerminal")
    public HttpResult<Object> updateTerminal(@Valid @RequestBody UpdateTerminalParam updateTerminalParam) {
        String methodDescribe = getMethodDescribe("updateTerminal");
        terminalBaseService.updateTerminal(updateTerminalParam);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }

    /**
     * 根据id level获取终端相关信息
     *
     * @author cdf
     * @date 2021/7/19
     */
    @ApiOperation("查询终端详情")
    @OperateInfo(info = LogEnum.BUSINESS_MEDIUM)
    @GetMapping("queryTerminal")
    public HttpResult<TerminalVO> queryTerminal(@RequestParam("id") String id,@RequestParam(required = false)Integer level) {
        String methodDescribe = getMethodDescribe("queryTerminal");
        TerminalVO t = terminalBaseService.queryTerminal(id,level);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, t, methodDescribe);
    }


    /**
     * 根据id和节点level删除当前节点以及下级节点
     *
     * @author cdf
     * @date 2021/7/21
     */
    @ApiOperation("终端删除操作")
    @OperateInfo(operateType = OperateType.DELETE, info = LogEnum.BUSINESS_SERIOUS)
    @DeleteMapping("delTerminal")
    public HttpResult<Object> delTerminal(@RequestParam("id") String id) {
        String methodDescribe = getMethodDescribe("delTerminal");
        terminalBaseService.delTerminal(id);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }


    /**
     * 功能描述:根据变电站id获取变电站详情
     *
     * @param list
     * @return
     * @author xy
     * @date 2022/2/21 18:53
     */
    @ApiOperation("获取变电站信息")
    @OperateInfo
    @PostMapping("/getSubstationById")
    @ApiIgnore
    public HttpResult<List<Line>> getSubstationById(@RequestBody List<String> list) {
        String methodDescribe = getMethodDescribe("getSubstationById");
        LogUtil.njcnDebug(log, "{}，变电站集合为：{}", methodDescribe, list);
        List<Line> subList = terminalBaseService.getSubstationById(list);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, subList, methodDescribe);
    }


    /**
     * 根据设备id集获取设备集信息
     *
     * @param list 设备集合
     * @author cdf
     * @date 2022/6/29
     */
    @ApiOperation("获取装置信息")
    @OperateInfo
    @PostMapping("/getDevInfoByIds")
    public HttpResult<List<TerminalBaseVO>> getDevInfoByIds(@RequestBody List<String> list) {
        String methodDescribe = getMethodDescribe("getDevInfoByIds");
        LogUtil.njcnDebug(log, "{}，设备集合为：{}", methodDescribe, list);
        List<TerminalBaseVO> devList = terminalBaseService.getDeviceByIdOnOrOff(list, new DeviceType(), 0);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, devList, methodDescribe);
    }

    /**
     * 获取区域中断设备
     * @author cdf
     * @date 2022/6/29
     */
    @OperateInfo(info = LogEnum.BUSINESS_COMMON)
    @PostMapping("/getAreaOffDev")
    @ApiOperation("获取区域中断设备")
    @ApiImplicitParam(name = "deviceInfoParam", value = "参数体", required = true)
    public HttpResult<List<TerminalBaseVO>> getAreaOffDev(@RequestBody @Validated DeviceInfoParam.BusinessParam deviceInfoParam) {
        String methodDescribe = getMethodDescribe("getAreaOffDev");
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfo(deviceInfoParam, Stream.of(0).collect(Collectors.toList()), Stream.of(1).collect(Collectors.toList()));
        List<String> devIds = generalDeviceDTOList.stream().flatMap(dto -> dto.getDeviceIndexes().stream()).collect(Collectors.toList());
        List<TerminalBaseVO> res = terminalBaseService.getDeviceByIdOnOrOff(devIds, new DeviceType(), 0);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, res, methodDescribe);
    }

    /**
     * 批量导入oracle中的原始数据
     *
     * @param file 上传的数据文件
     * @return 返回导入结果
     */
    @ResponseBody
    @ApiOperation("批量导入oracle中的原始数据")
    @PostMapping(value = "importOracleTerminalData")
    public HttpResult<String> importOracleTerminalData(@ApiParam(value = "文件", required = true) @RequestPart("file") MultipartFile file, HttpServletResponse response) {
        String methodDescribe = getMethodDescribe("importOracleTerminalData");
        if (Objects.isNull(terminalBaseService.importOracleTerminalData(file, response))) {
            return null;
        }
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }


    /**
     * 导出台账
     *
     * @author cdf
     * @date 2022/5/17
     */
    @ResponseBody
    @ApiOperation("导出台账信息")
    @GetMapping(value = "exportTerminalBase")
    public HttpResult<String> exportTerminalBase(HttpServletResponse response) {
        String methodDescribe = getMethodDescribe("exportTerminalBase");
        String fileName = "台账信息.xls";
        List<TerminalBaseExcel> baseExcelList = null;
        try {
            baseExcelList = terminalBaseService.exportTerminalBase();
        } catch (Exception e) {
            e.printStackTrace();
            return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe);
        }
        ExportParams exportExcel = new ExportParams("批量导入模板（请严格按照模板标准填入数据）", "台账信息");
        Workbook workbook = ExcelExportUtil.exportExcel(exportExcel, TerminalBaseExcel.class, baseExcelList);
        PoiUtil.exportFileByWorkbook(workbook, fileName, response);
        return null;
    }

    /**
     * 导出台账生成的excel
     *
     * @author cdf
     * @date 2022/5/17
     */
    @ApiOperation("导出台账模板")
    @GetMapping(value = "downTerminalTemplate")
    public void downTerminalTemplate(HttpServletResponse response) {
        terminalBaseService.downTerminalTemplate(response);
    }

    /**
     * 导出台账生成的excel(离线装置)
     *
     * @author zbj
     * @date 2023/4/26
     */
    @ApiOperation("导出台账模板(离线装置)")
    @GetMapping(value = "downTerminalAutonomeTemplate")
    public void downTerminalAutonomeTemplate(HttpServletResponse response) {
        terminalBaseService.downTerminalAutonomeTemplate(response);
    }

    /**
     * 导入excel台账模板
     *
     * @author cdf
     * @date 2022/5/18
     */
    @ResponseBody
    @ApiOperation("excel批量导入台账信息")
    @PostMapping(value = "importTerminalBase")
    public HttpResult<String> importTerminalBase(@ApiParam(value = "文件", required = true) @RequestPart("file") MultipartFile file, HttpServletResponse response) {
        String methodDescribe = getMethodDescribe("importTerminalBase");
        terminalBaseService.importTerminalBase(file, response);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }



    /**
     * 重新计算限值
     *
     * @author cdf
     * @date 2022/5/17
     */
    @ApiOperation("监测点-重新计算限值")
    @GetMapping(value = "updatePqOverLimit")
    public HttpResult<Integer> updatePqOverLimit() {
        String methodDescribe = getMethodDescribe("updatePqOverLimit");
        Integer count = terminalBaseService.updatePqOverLimit();
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, count, methodDescribe);
    }

    /**
     * 监测点主接线图上传
     * @author cdf
     * @date 2023/6/15
     */
    @ApiOperation("监测点主接线图上传")
    @PostMapping(value = "wiringDiagramUpload")
    @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType = OperateType.UPLOAD)
    public HttpResult<Boolean> wiringDiagramUpload(@ApiParam(value = "文件", required = true) @RequestPart("files") MultipartFile[] files,@RequestParam("lineId")String lineId) {
        String methodDescribe = getMethodDescribe("wiringDiagramUpload");
        terminalBaseService.wiringDiagramUpload(files,lineId);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }

    /**
     * 展示主接线图
     * @author cdf
     * @date 2023/6/16
     */
    @ApiOperation("展示主接线图")
    @PostMapping(value = "wiringDiagramShow")
    @OperateInfo(info = LogEnum.BUSINESS_COMMON)
    public HttpResult<List<LineWiringDiagramVO>> wiringDiagramShow(@RequestParam("lineId")String lineId) {
        String methodDescribe = getMethodDescribe("wiringDiagramShow");
        List<LineWiringDiagramVO> result = terminalBaseService.wiringDiagramShow(lineId);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
    }

    /**
     * 监测点主接线图变更
     * @author cdf
     * @date 2023/6/16
     */
    @ApiOperation("主接线图变更")
    @PostMapping(value = "wiringDiagramChange")
    @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType = OperateType.UPLOAD)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lineId", value = "监测点索引", required = true),
            @ApiImplicitParam(name = "wiringDiagramName", value = "主接线图名称", required = true)
    })
    public HttpResult<Object> wiringDiagramChange(@ApiParam(value = "文件", required = true) @RequestPart("file") MultipartFile file,@RequestParam("lineId")String lineId,@RequestParam("wiringDiagramName")String wiringDiagramName) {
        String methodDescribe = getMethodDescribe("wiringDiagramChange");
        boolean result = terminalBaseService.wiringDiagramChange(file,lineId,wiringDiagramName);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
    }

    /**
     * 监测点主接线图变更
     * @author cdf
     * @date 2023/6/16
     */
    @ApiOperation("主接线图删除")
    @PostMapping(value = "wiringDiagramDel")
    @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType = OperateType.DELETE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lineId", value = "监测点索引", required = true),
            @ApiImplicitParam(name = "wiringDiagramName", value = "主接线图名称", required = true)
    })
    public HttpResult<Object> wiringDiagramDel(@RequestParam("lineId")String lineId,@RequestParam("wiringDiagramName")String wiringDiagramName) {
        String methodDescribe = getMethodDescribe("wiringDiagramDel");
        boolean result = terminalBaseService.wiringDiagramDel(lineId,wiringDiagramName);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
    }

    @ApiOperation("请求前置重启进程")
    @PostMapping(value = "askRestartProcess")
    @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType = OperateType.DELETE)
    public HttpResult<Object> askRestartProcess(@RequestBody RestartParam restartParam) {
        String methodDescribe = getMethodDescribe("askRestartProcess");
        terminalBaseService.askRestartProcess(restartParam);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, true, methodDescribe);
    }

//    @ApiOperation("请求前置设备重启")
//    @PostMapping(value = "askRestartDevice")
//    @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType = OperateType.DELETE)
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "devId", value = "设备id", required = true),
//            @ApiImplicitParam(name = "deviceRebootType", value = "重启类型", required = true)
//    })
//    public HttpResult<Object> askRestartDevice(@RequestParam("devId")List<String> devIds,@RequestParam("deviceRebootType")String deviceRebootType,@RequestParam("processNo")Integer processNo) {
//        String methodDescribe = getMethodDescribe("askRestartDevice");
//        terminalBaseService.askRestartDevice(devIds,deviceRebootType,processNo);
//        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, true, methodDescribe);
//    }

    @ApiOperation("台账变更推送")
    @PostMapping(value = "ledgerChangePush")
    @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType = OperateType.QUERY)
    public HttpResult<List<PreCommandDTO>> ledgerChangePush() {
        String methodDescribe = getMethodDescribe("ledgerChangePush");
        List<PreCommandDTO> preCommandDTOList = terminalBaseService.ledgerChangePush();
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, preCommandDTOList, methodDescribe);
    }

    @ApiOperation("查询前置推送结果")
    @PostMapping(value = "getPushResult")
    @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType = OperateType.QUERY)
    public HttpResult<PushResultDTO> getPushResult(@RequestParam("guid")String guid) {
        String methodDescribe = getMethodDescribe("getPushResult");
        PushResultDTO result = terminalBaseService.getPushResult(guid);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
    }


}
