package com.pqs9300.controller.transaction;

import com.njcn.enums.LogTypeEnum;
import com.njcn.pojo.commons.DatePojo;
import com.njcn.pojo.commons.HttpResult;
import com.njcn.shiro.token.TokenManager;
import com.njcn.utils.AppConfig;
import com.njcn.utils.PubUtils;
import com.njcn.utils.ZipUtils;
import com.pqs9300.mapper.transaction.OverRunLogMapper;
import com.pqs9300.pojo.transaction.IndexPojo;
import com.pqs9300.pojo.transaction.OverRunLogDetail;
import com.pqs9300.pojo.transaction.Supervise;
import com.pqs9300.pojo.transaction.TransactionData;
import com.pqs9300.service.transaction.OverRunLogService;
import com.pqs9300.service.transaction.SuperviseService;
import com.pqs9300.util.SocketSender;
import com.pqs9300.util.WordUtil2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipOutputStream;

/**
 * @author hongawen
 * @date: 2020/6/24 14:38
 */
@Controller
@RequestMapping("transaction")
public class TransactionController {

    private static final Logger logger = LoggerFactory.getLogger(TransactionController.class);

    @Resource
    private SuperviseService superviseService;

    @Resource
    private OverRunLogService overRunLogService;

    @Resource
    private AppConfig appConfig;

    @Resource
    private OverRunLogMapper overRunLogMapper;

    @Resource
    private SocketSender socketSender;


    /**
     * @param supIndex   主表事务索引
     * @param excuteStep 接下来的操作 1是执行当前操作 2是上一步操作的更新
     */
    @GetMapping("/excuteNextStep")
    public ModelAndView EarlyWarning(String supIndex, Integer excuteStep, String stepCount) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("supIndex", supIndex);
        modelAndView.addObject("excuteStep", excuteStep);
        modelAndView.addObject("stepCount", stepCount);
        modelAndView.setViewName("business/transaction/indexNextStep");
        return modelAndView;
    }


    /**
     * 获取当前用户条件范围内的事务数据
     *
     * @param startTime 起始时间
     * @param endTime   截止时间
     * @param type      事务类型
     * @param progress  事务当前流程
     */
    @PostMapping("getTransactionData")
    @ResponseBody
    public HttpResult getTransactionData(String startTime, String endTime, Integer type, Integer progress, HttpServletRequest request) {
        HttpResult result = PubUtils.initResult(TokenManager.getToken().getLoginName(), request, LogTypeEnum.BUSSINESS.toString(), 0);
        DatePojo datePojo;
        datePojo = PubUtils.validateDate(startTime, endTime, "getTransactionData");
        if (!StringUtils.isEmpty(datePojo.getMsg())) {
            result = PubUtils.assignmentResult(null, 500, datePojo.getMsg());
            return result;
        }
       IndexPojo indexPojo;
        try {
            indexPojo = superviseService.getTransactionData(datePojo.getStartTime(), datePojo.getEndTime(), type, progress);
            if (CollectionUtils.isEmpty(indexPojo.getSuperviseList())) {
                result = PubUtils.assignmentResultLog(indexPojo, 500, "获取当前用户条件范围内的事务数据为空", "获取当前用户条件范围内的事务数据", "成功", result);
            } else {
                result = PubUtils.assignmentResultLog(indexPojo, 200, "获取当前用户条件范围内的事务数据成功", "获取当前用户条件范围内的事务数据", "成功", result);
            }
        } catch (Exception e) {
            logger.error("获取当前用户条件范围内的事务数据异常,异常为：" + e.toString());
            result = PubUtils.assignmentResultLog(null, 500, "获取当前用户条件范围内的事务数据异常", "获取当前用户条件范围内的事务数据", "失败", result);
        }
        return result;
    }

    /**
     * 根据主表索引获取出各监测点越限的详细数据
     *
     * @param supIndex 事务索引
     */
    @PostMapping("getMonitorDetailData")
    @ResponseBody
    public HttpResult getTransactionData(String supIndex, HttpServletRequest request) {
        HttpResult result = PubUtils.initResult(TokenManager.getToken().getLoginName(), request, LogTypeEnum.BUSSINESS.toString(), 0);
        TransactionData transactionData;
        try {
            transactionData = overRunLogService.getMonitorDetailData(supIndex);
            if (null == transactionData) {
                result = PubUtils.assignmentResultLog(null, 500, "获取出各监测点越限的详细数据为空", "获取出各监测点越限的详细数据", "成功", result);
            } else {
                result = PubUtils.assignmentResultLog(transactionData, 200, "获取出各监测点越限的详细数据成功", "获取出各监测点越限的详细数据", "成功", result);
            }
        } catch (Exception e) {
            logger.error("获取出各监测点越限的详细数据异常,异常为：" + e.toString());
            result = PubUtils.assignmentResultLog(null, 500, "获取出各监测点越限的详细数据异常", "获取出各监测点越限的详细数据", "失败", result);
        }
        return result;
    }


    /**
     * 用户点击开始执行事务
     *
     * @param supIndex 事务索引
     */
    @PostMapping("startDealTransaction")
    @ResponseBody
    public HttpResult startDealTransaction(String supIndex, HttpServletRequest request) {
        HttpResult result = PubUtils.initResult(TokenManager.getToken().getLoginName(), request, LogTypeEnum.BUSSINESS.toString(), 0);
        try {
            superviseService.startDealTransaction(supIndex);
            result = PubUtils.assignmentResultLog(null, 200, "用户点击开始执行事务成功", "用户点击开始执行事务", "成功", result);
            socketSender.sendSocketMsg("执行"+supIndex+"事务");
        } catch (Exception e) {
            logger.error("用户点击开始执行事务异常,异常为：" + e.toString());
            result = PubUtils.assignmentResultLog(null, 500, "用户点击开始执行事务异常", "用户点击开始执行事务", "失败", result);
        }
        return result;
    }


    /**
     * 根据事务索引校验后台的事务索引和报告文档是否存在
     *
     * @param supIndex 事务索引
     */
    @PostMapping("checkTransaction")
    @ResponseBody
    public HttpResult checkTransaction(String supIndex, HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        HttpResult result = PubUtils.initResult(TokenManager.getToken().getLoginName(), request, LogTypeEnum.BUSSINESS.toString(), 0);
        //先判断事务是否存在
        Supervise supervise;
        try {
            supervise = superviseService.isExist(supIndex);
            if (null == supervise) {
                result = PubUtils.assignmentResultLog(null, 500, "当前事务数据丢失", "预/告警单下载", "成功", result);
            } else {
                //再开始判断当前功能需求的模板文档是否存在
                Integer type = supervise.getType();
                InputStream ins;
                //判断有文件后，进行文档准备，保存进指定文件夹，待会提供下载
                String path = appConfig.getTmppath();
                String rtfPath = "";
                if (type == 0) {
                    //去找预警模板
                    ins = TransactionController.class.getClassLoader().getResourceAsStream("file/earlyWarn.docx");
                    if (null == ins) {
                        result = PubUtils.assignmentResultLog(null, 500, "模板丢失", "预/告警单下载", "成功", result);
                    } else {
                        ins.close();
                        path = path + "/njcn/transaction/earlyWarn/" + supervise.getName();
                        rtfPath = getClass().getClassLoader().getResource("file/earlyWarn.docx").getPath();
                        rtfPath = rtfPath.replaceAll("%20", " ");
                    }
                } else {
                    //去找告警模板
                    ins = TransactionController.class.getClassLoader().getResourceAsStream("file/alarm.docx");
                    if (null == ins) {
                        result = PubUtils.assignmentResultLog(null, 500, "模板丢失", "预/告警单下载", "成功", result);
                    } else {
                        ins.close();
                        path = path + "/njcn/transaction/alarm/" + supervise.getName();
                        rtfPath = getClass().getClassLoader().getResource("file/alarm.docx").getPath();
                        rtfPath = rtfPath.replaceAll("%20", " ");
                    }
                }

                //获取所有的监测点越限信息
                List<OverRunLogDetail> overRunLogList = overRunLogMapper.getMonitorDetailData(supIndex);
                if (CollectionUtils.isEmpty(overRunLogList)) {
                    //该事物没有监测点预警或者告警信息
                    result = PubUtils.assignmentResultLog(null, 500, "该事件没有监测点详细越限数据", "预/告警单下载", "成功", result);
                } else {
                    List<Map<String, Object>> totalData = new ArrayList<>();
                    for (OverRunLogDetail overRunLogDetail : overRunLogList) {
                        Map<String, Object> reportmap = new HashMap<>();
                        reportmap.put("date", PubUtils.date2String(overRunLogDetail.getOverRunLog().getUpdateTime(), "yyyy年MM月dd日"));
                        reportmap.put("gdName", overRunLogDetail.getGdName());
                        reportmap.put("deptsName", overRunLogDetail.getDeptsName());
                        reportmap.put("mark", overRunLogDetail.getOverRunLog().getOverRunDescribe());
                        reportmap.put("fileName", overRunLogDetail.getOverRunLog().getName() + ".docx");
                        totalData.add(reportmap);
                    }
                    //收集完信息，开始一个个的保存到对应的文件夹中，每个文件名：监测点名+年月日
                    WordUtil2 oRTF = new WordUtil2();
                    try {
                        oRTF.getWordWarn(rtfPath, totalData, path, response, session);
                    } catch (Exception e) {
                        logger.error("产生了异常，异常是"+e.getMessage());
                    }
                    result = PubUtils.assignmentResultLog(null, 200, "可以后台下载", "预/告警单下载", "成功", result);
                    //更新当前记录的各个状态，主表的流程+1，监测点谐波详细表的文件路径
                    superviseService.finishEarlyWarn(supervise);
                }
            }
        } catch (Exception e) {
            logger.error("获取出各监测点越限的详细数据异常,异常为：" + e.toString());
            result = PubUtils.assignmentResultLog(null, 500, "下载异常", "预/告警单下载", "失败", result);
        }
        return result;
    }


    /**
     * 下载预警、告警单
     * 找到指定文件夹，直接压缩下载
     *
     * @param supIndex 事务索引
     */
    @RequestMapping("downTransactionWord")
    public void downTransactionWord(HttpServletRequest request, HttpServletResponse response, String supIndex) throws IOException {
        socketSender.sendSocketMsg("下发"+supIndex+"事务单");
        Supervise supervise;
        supervise = superviseService.isExist(supIndex);
        Integer type = supervise.getType();
        //判断有文件后，进行文档准备，保存进指定文件夹，待会提供下载
        String path = appConfig.getTmppath();
        String zipName;
        if (type == 0) {
            path = path + "/njcn/transaction/earlyWarn/" + supervise.getName();
            zipName = supervise.getName() + "预警单";
        } else {
            path = path + "/njcn/transaction/alarm/" + supervise.getName();
            zipName = supervise.getName() + "告警单";
        }
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", "attachment; filename=" + encodeFileName(request, zipName) + ".zip");
        ZipOutputStream out = new ZipOutputStream(response.getOutputStream());
        try {
            ZipUtils.doCompress(path, out);
            response.flushBuffer();
        } catch (Exception e) {
            logger.error("下载预警单");
        } finally {
            out.close();
        }
    }


    /**
     * 根据事务索引校验后台的报告文档是否存在
     *
     * @param supIndex 事务索引
     */
    @PostMapping("checkTransactionNotice")
    @ResponseBody
    public HttpResult checkTransactionNotice(String supIndex, HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        HttpResult result = PubUtils.initResult(TokenManager.getToken().getLoginName(), request, LogTypeEnum.BUSSINESS.toString(), 0);
        //先判断事务是否存在
        Supervise supervise;
        try {
            supervise = superviseService.isExist(supIndex);
            if (null == supervise) {
                result = PubUtils.assignmentResultLog(null, 500, "当前事务数据丢失", "整改通知单下载", "成功", result);
            } else {
                //再开始判断当前功能需求的模板文档是否存在
                Integer type = supervise.getType();
                InputStream ins;
                //判断有文件后，进行文档准备，保存进指定文件夹，待会提供下载
                String path = appConfig.getTmppath();
                String rtfPath = "";
                //去找预警模板
                ins = TransactionController.class.getClassLoader().getResourceAsStream("file/notice.docx");
                if (null == ins) {
                    result = PubUtils.assignmentResultLog(null, 500, "模板丢失", "整改通知单下载", "成功", result);
                } else {
                    ins.close();
                    path = path + "/njcn/transaction/notice/" + supervise.getName();
                    rtfPath = getClass().getClassLoader().getResource("file/notice.docx").getPath();
                    rtfPath = rtfPath.replaceAll("%20", " ");
                }
                //获取所有的监测点越限信息
                List<OverRunLogDetail> overRunLogList = overRunLogMapper.getMonitorDetailData(supIndex);
                if (CollectionUtils.isEmpty(overRunLogList)) {
                    //该事物没有监测点预警或者告警信息
                    result = PubUtils.assignmentResultLog(null, 500, "该事件没有监测点详细越限数据", "整改通知单下载", "成功", result);
                } else {
                    List<Map<String, Object>> totalData = new ArrayList<>();
                    for (OverRunLogDetail overRunLogDetail : overRunLogList) {
                        Map<String, Object> reportmap = new HashMap<>();
                        reportmap.put("date", PubUtils.date2String(overRunLogDetail.getOverRunLog().getUpdateTime(), "yyyy年MM月dd日"));
                        reportmap.put("gdName", overRunLogDetail.getGdName());
                        reportmap.put("deptsName", overRunLogDetail.getDeptsName());
                        reportmap.put("mark", overRunLogDetail.getOverRunLog().getOverRunDescribe());
                        reportmap.put("fileName", overRunLogDetail.getOverRunLog().getName()+ ".docx");
                        totalData.add(reportmap);
                    }
                    //收集完信息，开始一个个的保存到对应的文件夹中，每个文件名：监测点名+年月日
                    WordUtil2 oRTF = new WordUtil2();
                    try {
                        oRTF.getWordWarn(rtfPath, totalData, path, response, session);
                    } catch (Exception e) {
                       logger.error("产生了异常，异常是"+e.getMessage());
                    }
                    result = PubUtils.assignmentResultLog(null, 200, "可以后台下载", "整改通知单下载", "成功", result);
                    //更新当前记录的各个状态，主表的流程+1，监测点谐波详细表的文件路径
                    superviseService.finishEarlyNotice(supervise);
                }
            }
        } catch (Exception e) {
            logger.error("获取出各监测点越限的详细数据异常,异常为：" + e.toString());
            result = PubUtils.assignmentResultLog(null, 500, "下载异常", "整改通知单下载", "失败", result);
        }
        return result;
    }


    /**
     * 下载整改通知单
     * 找到指定文件夹，直接压缩下载
     *
     * @param supIndex 事务索引
     */
    @RequestMapping("downTransactionWordNotice")
    public void downTransactionWordNotice(HttpServletRequest request, HttpServletResponse response, String supIndex) throws IOException {
        socketSender.sendSocketMsg("下发"+supIndex+"通知单");
        Supervise supervise;
        supervise = superviseService.isExist(supIndex);
        response.setContentType("APPLICATION/OCTET-STREAM");
        String zipName = supervise.getName() + "整改通知单";
        response.setHeader("Content-Disposition", "attachment; filename=" + encodeFileName(request, zipName) + ".zip");
        ZipOutputStream out = new ZipOutputStream(response.getOutputStream());
        try {
            //判断有文件后，进行文档准备，保存进指定文件夹，待会提供下载
            String path = appConfig.getTmppath();
            path = path + "/njcn/transaction/notice/" + supervise.getName();
            ZipUtils.doCompress(path, out);
            response.flushBuffer();
        } catch (Exception e) {
            logger.error("产生了异常，异常是"+e.getMessage());
        } finally {
            out.close();
        }
    }

    /**
     * 下载文件名中含有中文的处理
     */
    public static String encodeFileName(HttpServletRequest req, String headName)
            throws UnsupportedEncodingException {
        String filename = "";//IE9之前包括IE9都包含MSIE;IE10之后都包含Trident;edge浏览器包含Edge
        String userAgent = req.getHeader("User-Agent");
        if (userAgent.contains("MSIE") || userAgent.contains("Trident") || userAgent.contains("Edge")) {
            if (filename.length() > 150) {//解决IE 6.0 bug
                filename = new String(headName.getBytes("UTF-8"), "ISO-8859-1");
            } else {
                filename = URLEncoder.encode(headName, "UTF-8");
            }

        } else {
            filename = new String(headName.getBytes("UTF-8"), "ISO8859-1");
        }
        return filename;
    }

}
