package com.ho.business.controller;

import com.ho.business.entity.*;
import com.ho.business.feignclient.FileCenterFeignClient;
import com.ho.business.service.PlanningCurveService;
import com.ho.business.service.StationSnService;
import com.ho.business.vo.resp.planningCurve.PlanningCurveTemplateVo;
import com.ho.common.tools.annotation.HzPermission;
import com.ho.common.tools.annotation.LogAnnotation;
import com.ho.common.tools.annotation.TokenIgnore;
import com.ho.common.tools.constant.*;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.entity.UserDetailRespVO;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.EasyExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

@RestController
@RequestMapping(ContextConstant.BUSINESS + "planning")
@Api(tags = "计划曲线")
@Slf4j
public class PlanningCurveController {

    // 下发文件地址
    public static final String FILE_PATH = "/deploy/sems/data";

    // 生成的json文件名称
    public static final String JSON_FILE_NAME = "svc_plantemplate.json";

    // 压缩包保存位置及名称
    public static final String TAR_GZ_FILE_PATH = "/usr/temporaryFiles/svc_plantemplate.tar.gz";

    @Autowired
    private PlanningCurveService planningService;

    @Autowired
    RedisService redisService;

    @Autowired
    StationSnService stationSnService;

    @Autowired
    FileCenterFeignClient fileCenterFeignClient;

    /**
     * 查询模板列表接口
     *
     * @param template
     * @return
     */
    @PostMapping("getPlanningCurveTemplates")
    @ApiOperation(value = "模板列表查询")
    @TokenIgnore
    public DataResult getPlanningCurveTemplates(@RequestBody PlanningCurveTemplate template,HttpServletRequest request) {
        template.setLang(request.getHeader(CommonConstant.LANG));
        List<Map<String, Object>> planningCurveTemplates = planningService.getPlanningCurveTemplates(template);
        return DataResult.success(planningCurveTemplates);
    }

    /**
     * 编辑页面 新增接口
     *
     * @param template
     * @return
     */
    @PostMapping("addPlanningCurveTemplate")
    @ApiOperation(value = "新增模板")
    @LogAnnotation(title = "模板列表查询", action = "新增模板")
    @TokenIgnore
    @HzPermission(PermissionConstant.STRATEGY_PLANCURVE_ADD)
    public DataResult addPlanningCurveTemplate(HttpServletRequest request, @RequestBody PlanningCurveTemplate template) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        if (null != simpleUser && null != template) {
            template.setGroupId(simpleUser.getGroupId());
        }
        Map<String, Object> result = planningService.addPlanningCurveTemplate(template);
        return DataResult.success(result);
    }

    /**
     * 编辑页面 查看详情接口
     *
     * @param template
     * @return
     */
    @PostMapping("planningCurveTemplateDetail")
    @ApiOperation(value = "查看详情")
    @TokenIgnore
    public DataResult planningCurveTemplateDetail(@RequestBody PlanningCurveTemplate template,HttpServletRequest request) {
        template.setLang(request.getHeader(CommonConstant.LANG));
        if( template == null || template.getTemId() == null ){
            return DataResult.success();
        }
        List<PlanningCurveTemplate> planningCurveTemplates = planningService.getPlanningCurveTemplate(template);
        return DataResult.success(planningCurveTemplates);
    }


    @PostMapping("exportPlanningCurveTemplateDetail")
    @ApiOperation(value = "查看详情")
    @TokenIgnore
    public void exportPlanningCurveTemplateDetail(@RequestBody PlanningCurveTemplate template, HttpServletResponse response)  {
        List<PlanningCurveTemplate> planningCurveTemplates = planningService.getPlanningCurveTemplate(template);
        List<PlanningCurve> planningCurves = planningCurveTemplates.get(0).getPlanningCurves();
        List<PlanningCurveExport> exportList = new ArrayList<>();
        for(PlanningCurve planningCurveDetail:planningCurves){
            PlanningCurveExport planningCurveExport = new PlanningCurveExport();
            planningCurveExport.setTime(planningCurveDetail.getStartTime()+"--"+planningCurveDetail.getEndTime());
            planningCurveExport.setP(planningCurveDetail.getP());
            exportList.add(planningCurveExport);
        }
        String fileName = "计划曲线";
        String sheetName = "计划曲线";
        try{
            EasyExcelUtil.writeExcel(response,exportList, fileName, sheetName,PlanningCurveExport.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 编辑页面 编辑接口
     *
     * @param template
     * @return
     */
    @PostMapping("modifyPlanningCurveTemplate")
    @ApiOperation(value = "编辑模板")
    @LogAnnotation(title = "模板列表查询", action = "编辑模板")
    @TokenIgnore
    @HzPermission(PermissionConstant.STRATEGY_PLANCURVE_EDIT)
    public DataResult modifyPlanningCurveTemplate(@RequestBody PlanningCurveTemplate template) {
        Map<String, Object> result = planningService.modifyPlanningCurveTemplate(template);
        return DataResult.success(result);
    }

    /**
     * 删除接口（支持批量）
     *
     * @param ids
     * @return
     */
    @PostMapping("deletePlanningCurveTemplates")
    @ApiOperation(value = "删除模板")
    @LogAnnotation(title = "模板列表查询", action = "删除模板")
    @TokenIgnore
    @HzPermission(value = {PermissionConstant.STRATEGY_PLANCURVE_DELETE,PermissionConstant.STRATEGY_PLANCURVE_SINGLEDELETE})
    public DataResult deletePlanningCurveTemplates(@RequestBody List<Integer> ids) {
        Map<String, Object> result = planningService.deletePlanningCurveTemplates(ids);
        return DataResult.success(result);
    }

    // 导入
    @PostMapping("uploadData")
    @ApiOperation(value = "上传文件")
    @LogAnnotation(title = "模板列表查询", action = "上传文件")
    @TokenIgnore
    public DataResult uploadData(HttpServletRequest request, @RequestParam MultipartFile file) {
        Map<String, Object> result = new HashMap<String, Object>(0);
        try {
            if (file != null && file.getSize() > 0) {
                String fileName = file.getOriginalFilename();
                result = planningService.batchImport(fileName, file);
            } else {
                result.put("code", "400");
                result.put("msg", DefineConstant.CommonFile.CHOOSE_FILE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.put("code", 500);
            result.put("msg", DefineConstant.CommonFile.FILE_UPLOAD_ERROR);
        }
        return DataResult.success(result);
    }

    // 导出

    /**
     * 导出点表数据
     *
     * @param response
     */
    @PostMapping("/exportExcel")
    @ApiOperation(value = "导出计划曲线模板数据")
    @LogAnnotation(title = "模板列表查询", action = "导出计划曲线模板数据")
    @TokenIgnore
    public void exportExcel(@RequestBody PlanningCurveTemplate template, HttpServletResponse response) {
        List<PlanningCurveTemplate> planningCurveTemplates = planningService.getPlanningCurveTemplate(template);
        String fileName = "计划曲线模板";
        // 合并行长度集合
        List<Integer> exportFieldGroupCountList = new ArrayList<Integer>(0);
        try {
            Map<String, Object> dataMap = new HashMap<String, Object>();

            List<PlanningCurveTemplateVo> list = new ArrayList<>(0);

            PlanningCurveTemplateVo vo = null;

            // 组装导出数据
            for (PlanningCurveTemplate planningCurveTemplate : planningCurveTemplates) {
                List<PlanningCurve> planningCurves = planningCurveTemplate.getPlanningCurves();
                exportFieldGroupCountList.add(planningCurves.size());
                for (PlanningCurve planningCurve : planningCurves) {
                    vo = new PlanningCurveTemplateVo();
                    vo.setTemplateNo(planningCurveTemplate.getTemplateNo());
                    vo.setTemplateName(planningCurveTemplate.getTemplateName());
                    vo.setStartTime(planningCurve.getStartTime());
                    vo.setEndTime(planningCurve.getEndTime());
                    vo.setP(planningCurve.getP());
                    vo.setStatus(planningCurveTemplate.getStatus() == 0?"不启用":"启用");
                    vo.setUpdateTime(planningCurveTemplate.getUpdateTime());
                    list.add(vo);
                }
            }
            dataMap.put("list",list);
            EasyExcelUtil.mergeExport("template/planningCurveTemplate.xlsx", dataMap, fileName, response, exportFieldGroupCountList, Arrays.asList(0,1,5,6));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 编辑页面 查看详情接口
     *
     * @param template
     * @return
     */
    @PostMapping("planningCurveTemplateChartData")
    @ApiOperation(value = "查看详情曲线")
    @TokenIgnore
    public DataResult planningCurveTemplateChartData(@RequestBody PlanningCurveTemplate template) {
        if( template == null || template.getTemId() == null ){
            return DataResult.success();
        }
        List<PlanningCurveTemplate> planningCurveTemplates = planningService.planningCurveTemplateChartData(template);
        return DataResult.success(planningCurveTemplates);
    }




    public static void wirteFile(String filePath,String json){
        try (FileWriter writer = new FileWriter(filePath, true)) {
            writer.write(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static Map<String, Object>  compressFileToTarGz(File fileToCompress, File tarGzFile){
        Map<String, Object> result = new HashMap<String, Object>(0);
        try (FileInputStream fis = new FileInputStream(fileToCompress);
             FileOutputStream fos = new FileOutputStream(tarGzFile);
             GzipCompressorOutputStream gzos = new GzipCompressorOutputStream(fos);
             TarArchiveOutputStream taos = new TarArchiveOutputStream(gzos)) {
            TarArchiveEntry entry = new TarArchiveEntry(fileToCompress);
            entry.setSize(fileToCompress.length());
            taos.putArchiveEntry(entry);
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                taos.write(buffer, 0, bytesRead);
            }
            taos.closeArchiveEntry();
        } catch (IOException e) {
            e.printStackTrace();
            result.put("code", 500);
            result.put("msg", DefineConstant.PeakShaving.TAR_FILE_ISSUE_ERROR);
        }
        return result;
    }


    @PostMapping("planningCurveFile")
    @ApiOperation(value = "获取计划曲线json文件")
    @TokenIgnore
    public DataResult getPlanningCurveJson(HttpServletRequest request,HttpServletResponse response,@RequestBody PlanningTemplateVo template){
        Map<String, Object> result = new HashMap<String, Object>(0);
        //当前登陆人
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        UserDetailRespVO userDetail = redisService.getUserDetailByToken(token);
        // 获取到的json字符串
        String json = planningService.getJson(template, userDetail);
        // json字符串写出json文件,方便后面压缩
        wirteFile(JSON_FILE_NAME,json);
        // 取得json文件
        File fileToCompress = new File(JSON_FILE_NAME);
        // 生成一个空的压缩文件
        File tarGzFile = new File(TAR_GZ_FILE_PATH);
//        File tarGzFile = new File("D:/svc_plantemplate.tar.gz");

        // 对json文件进行压缩
        result = compressFileToTarGz(fileToCompress, tarGzFile);

        if( fileToCompress.exists() ){
            if (fileToCompress.delete()) {
                System.out.println("临时文件删除成功！");
            } else {
                System.out.println("临时文件删除失败！");
            }
        } else {
            System.out.println("临时文件不存在！");
        }
        result = uploadFile(template,tarGzFile);
        if( tarGzFile.exists() ){
            if (tarGzFile.delete()) {
                System.out.println("临时压缩包删除成功！");
            } else {
                System.out.println("临时压缩包删除失败！");
            }
        } else {
            System.out.println("临时压缩包不存在！");
        }
        return DataResult.success(result);
    }

    private Map<String, Object> uploadFile(PlanningTemplateVo template,File tarGzFile){
        Map<String, Object> result = new HashMap<String, Object>(0);
        result.put("code",200);
        result.put("msg", DefineConstant.PlanningCurve.FILE_ISSUE_SUCCESS);
        Integer stationId = template.getStationId();
        List<StationSn> snList = stationSnService.getSnListByStationId(stationId);
        String serialNo = "";
        for (StationSn stationSn : snList) {
            serialNo = stationSn.getSn();
        }
        try {
            FileInputStream input = new FileInputStream(tarGzFile);
            MockMultipartFile multipartFile = new MockMultipartFile("file", tarGzFile.getName(), "multipart/form-data", input);
            DataResult<HeartbeatResp> heartbeatRespDataResult = fileCenterFeignClient.fileUploadForDevice(multipartFile, stationId, serialNo, FILE_PATH);
            HeartbeatResp data = heartbeatRespDataResult.getData();
            List<OrderIssuedVO> list = template.getOrderIssuedReqVO();
            OrderIssuedReqVO vo = new OrderIssuedReqVO();
            if( data.getHeartbeatStatus().equals(CommonConstant.ONE) && list != null && list.size() > 0 ){
                vo.setSn(serialNo);
                // 进来则表示成功,下发额外的指令
                vo.setList(list);
                sendYC(vo);
            } else {
                result.put("code", 500);
                result.put("msg", DefineConstant.PlanningCurve.FILE_ISSUE_FAIL);
            }
        } catch (IOException e) {
            e.printStackTrace();
            result.put("code", 500);
            result.put("msg", DefineConstant.PeakShaving.FILE_ISSUE_ERROR);
        }
        return result;
    }

    private void sendYC( OrderIssuedReqVO vo ){
        DataResult<HeartbeatResp> heartbeatRespDataResult = fileCenterFeignClient.orderIssued(vo);
        HeartbeatResp data = heartbeatRespDataResult.getData();
    }




}
