package com.ho.business.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.ho.business.entity.DropDownVo;
import com.ho.business.entity.PlanningCurveTemplate;
import com.ho.business.entity.PlanningPolicy;
import com.ho.business.service.PlanningPolicyService;
import com.ho.common.tools.annotation.LogAnnotation;
import com.ho.common.tools.constant.ContextConstant;
import com.ho.common.tools.constant.DefineConstant;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.EasyExcelUtil;
import com.ho.common.tools.util.SelectSheetWriteHandler;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping(ContextConstant.BUSINESS + "policy")
@Api(tags = "计划曲线策略")
@Slf4j
public class PlanningPolicyController {

    @Autowired
    private PlanningPolicyService policyService;

    @Autowired
    RedisService redisService;

    private final String REDIS_KEY = "PLANNING_POLICY";

    private final List<String> HEAD_LIST = Arrays.asList("策略类型","名称","自定义策略名称","自定义策略开始时间","自定义策略结束时间","计划曲线模板","策略优先级","生效类型","生效开始时间","生效结束时间","是否启用","描述");

    public static final Map<Integer, String> EFFECTIVE_TYPE = new HashMap<Integer, String>() {{
        put(0, "永久生效");
        put(1, "时间段内生效");
    }};

    /**
     * 策略列表查询
     *
     * @param policy
     * @return
     */
    @PostMapping("getPlanningPolicys")
    @ApiOperation(value = "策略列表查询")
    //@TokenIgnore
    public DataResult getPlanningPolicys(@RequestBody(required = false) PlanningPolicy policy) {
        return DataResult.success(policyService.getPlanningPolicys(policy));
    }

    /**
     * 策略详情查询（编辑
     *
     * @param policy
     * @return
     */
    @PostMapping("getPlanningPolicyDetail4Modify")
    @ApiOperation(value = "策略详情查询（详情按钮、编辑）")
    //@TokenIgnore
    public DataResult getPlanningPolicyDetail4Modify(@RequestBody PlanningPolicy policy) {
        return DataResult.success(policyService.getPlanningPolicyDetail4Modify(policy));
    }

    /**
     * 新增策略
     *
     * @param policy
     * @return
     */
    @PostMapping("addPlanningPolicy")
    @ApiOperation(value = "新增策略")
    @LogAnnotation(title = "计划曲线策略", action = "新增策略")
    //@TokenIgnore
    public DataResult addPlanningPolicy(@RequestBody PlanningPolicy policy) {
        return DataResult.success(policyService.addPlanningPolicy(policy));
    }

    /**
     * 编辑策略
     *
     * @param policy
     * @return
     */
    @PostMapping("modifyPlanningPolicy")
    @ApiOperation(value = "编辑策略")
    @LogAnnotation(title = "计划曲线策略", action = "编辑策略")
    //@TokenIgnore
    public DataResult modifyPlanningPolicy(@RequestBody PlanningPolicy policy) {
        return DataResult.success(policyService.modifyPlanningPolicy(policy));
    }

    /**
     * 删除策略
     *
     * @param ids
     * @return
     */
    @PostMapping("deletePlanningPolicy")
    @ApiOperation(value = "删除策略")
    @LogAnnotation(title = "计划曲线策略", action = "删除策略")
    //@TokenIgnore
    public DataResult deletePlanningPolicy(@RequestBody List<Integer> ids) {
        return DataResult.success(policyService.deletePlanningPolicy(ids));
    }


    @PostMapping("queryPolicyTypes")
    @ApiOperation(value = "查询策略类型列表")
    //@TokenIgnore
    public DataResult queryPolicyTypes() {
        List<DropDownVo> vo = null;
        if (redisService.hasKey(REDIS_KEY + "TYPE")) {
            vo = (List<DropDownVo>) redisService.get(REDIS_KEY + "TYPE");
        } else {
            vo = policyService.queryPolicyTypes();
            redisService.set(REDIS_KEY + "TYPE", vo, 10, TimeUnit.MINUTES);
        }
        return DataResult.success(vo);
    }

    @PostMapping("queryPolicyPriority")
    @ApiOperation(value = "查询策略优先级列表")
    //@TokenIgnore
    public DataResult queryPolicyPriority() {
        List<DropDownVo> vo = null;
        if (redisService.hasKey(REDIS_KEY + "PRIORITY")) {
            vo = (List<DropDownVo>) redisService.get(REDIS_KEY + "PRIORITY");
        } else {
            vo = policyService.queryPolicyPriority();
            redisService.set(REDIS_KEY + "PRIORITY", vo, 10, TimeUnit.MINUTES);
        }
        return DataResult.success(vo);
    }

    // 导入
    @PostMapping("uploadData")
    @ApiOperation(value = "导入文件")
    @LogAnnotation(title = "计划曲线策略", action = "导入文件")
    //@TokenIgnore
    public DataResult uploadData(HttpServletRequest request, @RequestParam MultipartFile file,Integer stationId) {
        Map<String, Object> result = new HashMap<String, Object>(0);
        try {
            if (file != null && file.getSize() > 0) {
                String fileName = file.getOriginalFilename();
                result = policyService.batchImport(fileName, file,stationId);
            } 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);
    }

    @PostMapping(value="/exportTemplate",produces = {MediaType.APPLICATION_STREAM_JSON_VALUE})
    @ApiOperation(value = "导出计划曲线策略模板")
    @LogAnnotation(title = "计划曲线策略", action = "导出计划曲线策略模板")
    //@TokenIgnore
    public void exportTemplate(@RequestBody PlanningPolicy policy, HttpServletResponse response){
        String templateName = "策略模板";
        ServletOutputStream out = null;
        ZipOutputStream zipOutputStream = null;
        try {
            response.setCharacterEncoding("utf-8");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + URLEncoder.encode(templateName, "UTF-8"));

            out = response.getOutputStream();
            zipOutputStream = new ZipOutputStream(out);
            // 定义表头
            List<List<String>> headList = new ArrayList<>();
            List<String> temporaryList = null;
            //headList.add(HEAD_LIST);
            for (String s : HEAD_LIST) {
                temporaryList = new ArrayList<>();
                temporaryList.add(s);
                headList.add(temporaryList);
            }

            // 定义数据体
            List<Object> dataList = new ArrayList<>();

            HashMap<Integer, List<String>> dropDownMap = new HashMap<>();

            // 策略类型、策略级别数据集
            List<DropDownVo> vo = null;

            List<String> datas = new ArrayList<>(0);

            // 下拉框数据（策略类型）
            if (redisService.hasKey(REDIS_KEY + "TYPE")) {
                vo = (List<DropDownVo>) redisService.get(REDIS_KEY + "TYPE");
            } else {
                vo = policyService.queryPolicyTypes();
            }
            for (DropDownVo dropDownVo : vo) {
                datas.add(dropDownVo.getName());
            }
            // 存储需要下拉框的值，这里的key是需要设置为下拉框的列数，value是下拉框的值，是list
            if (datas != null && datas.size() > 0) {
                dropDownMap.put(0, datas);
            }

            // 下拉框数据（计划曲线模板）
            List<PlanningCurveTemplate> planningCurveTemplates = policyService.getPlanningCurveTemplates(policy.getStationId());
            datas = new ArrayList<>(0);
            for (PlanningCurveTemplate planningCurveTemplate : planningCurveTemplates) {
                datas.add(planningCurveTemplate.getTemplateName());
            }
            // 存储需要下拉框的值，这里的key是需要设置为下拉框的列数，value是下拉框的值，是list
            if (datas != null && datas.size() > 0) {
                dropDownMap.put(5, datas);
            }

            // 下拉框数据（策略级别）
            datas = new ArrayList<>(0);
            if (redisService.hasKey(REDIS_KEY + "PRIORITY")) {
                vo = (List<DropDownVo>) redisService.get(REDIS_KEY + "PRIORITY");
            } else {
                vo = policyService.queryPolicyPriority();
            }
            for (DropDownVo dropDownVo : vo) {
                datas.add(dropDownVo.getName());
            }
            // 存储需要下拉框的值，这里的key是需要设置为下拉框的列数，value是下拉框的值，是list
            if (datas != null && datas.size() > 0) {
                dropDownMap.put(6, datas);
            }

            datas = new ArrayList<>(0);
            datas.add("永久生效");
            datas.add("时间段内生效");
            dropDownMap.put(7, datas);

            datas = new ArrayList<>(0);
            datas.add("启用");
            datas.add("不启用");
            dropDownMap.put(10, datas);

            ExcelWriter excelWriter = EasyExcel.write().excelType(ExcelTypeEnum.XLS).build();
            //构建一个sheet页
            WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build();
            // 头的策略
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            // 单元格策略
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 初始化表格样式
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
            // 是设置下拉框的类
            new SelectSheetWriteHandler(dropDownMap);
            WriteTable writeTable = EasyExcel.writerTable(0).head(headList).registerWriteHandler(horizontalCellStyleStrategy).registerWriteHandler(new SelectSheetWriteHandler(dropDownMap)).needHead(Boolean.TRUE).build();
            excelWriter.write(dataList, writeSheet, writeTable);
            // 开始导出
            Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
            //创建压缩文件
            ZipEntry zipEntry = new ZipEntry("策略模板.xls");
            zipOutputStream.putNextEntry(zipEntry);
            //将excel对象以流的形式写入压缩流
            workbook.write(zipOutputStream);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            try {
                zipOutputStream.flush();
                zipOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }

    @PostMapping("/exportExcel")
    @ApiOperation("导出计划曲线策略")
    @LogAnnotation(title = "计划曲线策略", action = "导出计划曲线策略")
    //@TokenIgnore
    public void exportExcel(@RequestBody PlanningPolicy policy,HttpServletResponse response) {
        String fileName = "计划曲线策略";
        String sheetName = "计划曲线策略";
        try {
            List<PlanningPolicy> planningPolicys = policyService.getPlanningPolicys(policy);
            EasyExcelUtil.writeExcel(response, planningPolicys, fileName, sheetName, PlanningPolicy.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
