package com.ruoyi.web.controller.zhdd;

import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.zhdd.domain.Incident;
import com.ruoyi.zhdd.domain.IncidentProcess;
import com.ruoyi.zhdd.domain.IncidentTaskCommand;
import com.ruoyi.zhdd.domain.IncidentTaskPerson;
import com.ruoyi.zhdd.domain.Plan;
import com.ruoyi.zhdd.domain.PlanFile;
import com.ruoyi.zhdd.domain.bo.IncidentBo;
import com.ruoyi.zhdd.domain.bo.IncidentTasksBo;
import com.ruoyi.zhdd.domain.vo.IncidentTaskCommandVo;
import com.ruoyi.zhdd.domain.vo.IncidentTaskVo;
import com.ruoyi.zhdd.domain.vo.IncidentVo;
import com.ruoyi.zhdd.domain.vo.PlanFileVo;
import com.ruoyi.zhdd.domain.vo.PlanVo;
import com.ruoyi.zhdd.feign.FeignNoticeInfoService;
import com.ruoyi.zhdd.service.IIncidentProcessService;
import com.ruoyi.zhdd.service.IIncidentService;
import com.ruoyi.zhdd.service.IIncidentTaskCommandService;
import com.ruoyi.zhdd.service.IIncidentTaskPersonService;
import com.ruoyi.zhdd.service.IIncidentTaskService;
import com.ruoyi.zhdd.service.IPlanFileService;
import com.ruoyi.zhdd.service.IPlanService;
import com.ruoyi.zhdd.service.IPlanTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 事件基础Controller
 *
 * @author xitong
 * @date 2021-09-28
 */
@Validated
@Api(value = "事件基础控制器", tags = {"事件基础管理"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/zhdd/incident")
public class IncidentController extends BaseController {

    private final IIncidentService iIncidentService;

    private final IIncidentTaskService incidentTaskService;

    private final IIncidentTaskPersonService incidentTaskPersonService;

    private final IIncidentTaskCommandService incidentTaskCommandService;

    private final IIncidentProcessService iIncidentProcessService;

    private final IPlanTaskService planTaskService;

    private final IPlanService planService;

    private final IPlanFileService planFileService;

    private final ISysDictDataService sysDictDataService;

    private final FeignNoticeInfoService feignNoticeInfoService;

    @Value("${spring.profiles.active}")
    private String env;

    /**
     * 查询事件基础列表
     */
    @ApiOperation("查询事件基础列表")
//    @PreAuthorize("@ss.hasPermi('zhdd:incident:list')")
    @GetMapping("/list")
    public TableDataInfo<IncidentVo> list(@Validated(QueryGroup.class) IncidentBo bo) {
        return iIncidentService.queryPageList(bo);
    }

    /**
     * 导出事件基础列表
     */
    @ApiOperation("导出事件基础列表")
//    @PreAuthorize("@ss.hasPermi('zhdd:incident:export')")
//    @Log(title = "事件基础", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public void export(@Validated IncidentBo bo, HttpServletResponse response) {
        List<IncidentVo> list = iIncidentService.queryList(bo);
        ExcelUtil.exportExcel(list, "事件基础", IncidentVo.class, response);
    }

    /**
     * 获取事件基础详细信息
     */
    @ApiOperation("获取事件基础详细信息")
//    @PreAuthorize("@ss.hasPermi('zhdd:incident:query')")
    @GetMapping("/{id}")
    public AjaxResult<Map<String, Object>> getInfo(@NotNull(message = "主键不能为空")
                                                   @PathVariable("id") String id) {
        Map<String, Object> map = new HashMap<>();
        List<PlanFileVo> planFileVos = new ArrayList<>();
        IncidentVo incidentVo = iIncidentService.queryById(id);
        map.put("baseInfo", incidentVo);
        // 查询所属预案
        List<PlanVo> voOne = planService.listVo(Wrappers.<Plan>lambdaQuery().eq(Plan::getType, incidentVo.getType()).eq(Plan::getCreateDept, incidentVo.getCreateDept()));
        if (voOne != null && voOne.size() > 0) {
            map.put("baseTask", planTaskService.queryPlanTaskByPlanId(voOne.get(0).getId()));
            // 查询预案附件
            planFileVos = planFileService.listVo(Wrappers.<PlanFile>lambdaQuery().eq(PlanFile::getPlanId, voOne.get(0).getId()));
        } else {
            map.put("baseTask", null);
        }
        map.put("planFile", planFileVos);
        // 查询处置方案
        map.put("task", incidentTaskService.listTaskInfo(id));
        List<IncidentProcess> list = iIncidentProcessService.list(Wrappers.<IncidentProcess>lambdaQuery()
            .eq(IncidentProcess::getIncidentId, id).orderByAsc(IncidentProcess::getCreateTime));
        if (!"dev".equals(env)) {
            for (IncidentProcess incidentProcess : list) {
                if (incidentProcess.getStatus() == 1) {
                    // 查询阅读情况
                    JSONObject o = feignNoticeInfoService.messagePushInfoList("1", "2", incidentProcess.getId());
                    // 解析
                    if (ObjectUtil.isNotEmpty(o)) {
                        Integer total = o.getInt("total");
                        if (total > 0) {
                            JSONArray jsonArray = JSONUtil.parseObj(o.getJSONArray("rows").get(0)).getJSONArray("messageReadInfoList");
                            String unMessage = "";
                            String message = "";
                            for (Object o1 : jsonArray) {
                                JSONObject jsonObject = JSONUtil.parseObj(o1);
                                if ("0".equals(jsonObject.getStr("readState"))) {
                                    // 未读
                                    unMessage = jsonObject.getStr("nickName") + "、";
                                } else if ("1".equals(jsonObject.getStr("readState"))) {
                                    // 已读
                                    message = jsonObject.getStr("nickName") + "、";
                                }
                            }
                            // 循环完之后，去除最后一个顿号
                            if (StrUtil.isNotBlank(unMessage)) {
                                unMessage = StrUtil.removeSuffix(unMessage, "、");
                            }
                            if (StrUtil.isNotBlank(message)) {
                                message = StrUtil.removeSuffix(message, "、");
                            }
                            incidentProcess.setUserRead(message);
                            incidentProcess.setUserUnRead(unMessage);
                        }
                    }
                }
            }
        }
        map.put("process", list);
        return AjaxResult.success(map);
    }

    /**
     * 新增事件基础
     */
    @ApiOperation("新增事件基础")
//    @PreAuthorize("@ss.hasPermi('zhdd:incident:add')")
//    @Log(title = "事件基础", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody IncidentBo bo) {
        // 新增初始化为预警状态
        bo.setStatus(1);
        return toAjax(iIncidentService.insertByBo(bo) ? 1 : 0);
    }

    /**
     * 修改事件基础
     */
    @ApiOperation("修改事件基础")
//    @PreAuthorize("@ss.hasPermi('zhdd:incident:edit')")
//    @Log(title = "事件基础", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody IncidentBo bo) {
        return toAjax(iIncidentService.updateByBo(bo) ? 1 : 0);
    }

    /**
     * 删除事件基础
     */
    @ApiOperation("删除事件基础")
//    @PreAuthorize("@ss.hasPermi('zhdd:incident:remove')")
    @Log(title = "事件基础", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
                                   @PathVariable String[] ids) {
        return toAjax(iIncidentService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
    }

    @ApiOperation("新增事件方案")
//    @Log(title = "事件方案", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/task")
    public AjaxResult<Void> addTask(@Validated(AddGroup.class) @RequestBody IncidentTasksBo bo) {
        return toAjax(incidentTaskService.insertByBo(bo) ? 1 : 0);
    }

    @ApiOperation("删除事件方案")
//    @Log(title = "事件方案", businessType = BusinessType.DELETE)
    @DeleteMapping("/task/{ids}")
    public AjaxResult<Void> removeTask(@NotEmpty(message = "主键不能为空")
                                       @PathVariable String[] ids) {
        return toAjax(incidentTaskService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
    }

    @ApiOperation("查询事件-用于首页地图展示")
    @GetMapping("/location")
    public AjaxResult<Map<String, List<IncidentVo>>> queryIncidentLocation() {
        List<IncidentVo> list = iIncidentService.listVo(Wrappers.<Incident>lambdaQuery().in(Incident::getStatus, 1, 2, 3));
        Map<Integer, List<IncidentVo>> collect = list.stream().collect(Collectors.groupingBy(IncidentVo::getStatus, Collectors.mapping(a -> a, Collectors.toList())));
        Map<String, List<IncidentVo>> result = new HashMap<>();
        result.put("预警事件", CollUtil.defaultIfEmpty(collect.get(1), new ArrayList<>()));
        result.put("待派发", CollUtil.defaultIfEmpty(collect.get(2), new ArrayList<>()));
        result.put("待处置", CollUtil.defaultIfEmpty(collect.get(3), new ArrayList<>()));
        return AjaxResult.success(result);
    }

    @ApiOperation("应急方案导出")
//    @Log(title = "应急方案导出", businessType = BusinessType.EXPORT)
    @GetMapping("/download")
    public void download(@RequestParam String id, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<>();
        // 查询处置方案
        IncidentTaskVo incidentTaskVo = incidentTaskService.queryById(id);
        if (incidentTaskVo != null) {
            map.put("taskName", incidentTaskVo.getTaskName());

            // 查询事件详情
            IncidentVo incidentVo = iIncidentService.queryById(incidentTaskVo.getIncidentId());
            if (incidentVo != null) {
                map.put("name", incidentVo.getName());
                if (ObjectUtil.isNotEmpty(incidentVo.getType())) {
                    map.put("type", sysDictDataService.selectDictLabel("zhdd_plan_type", Convert.toStr(incidentVo.getType())));
                } else {
                    map.put("type", "-");
                }
                map.put("createTime", DateUtil.formatDateTime(incidentVo.getCreateTime()));
                map.put("addr", incidentVo.getAddr());
                if (StrUtil.isNotBlank(incidentVo.getSource())) {
                    map.put("source", sysDictDataService.selectDictLabel("zhdd_incident_source", incidentVo.getSource()));
                } else {
                    map.put("source", "-");
                }
                if (ObjectUtil.isNotEmpty(incidentVo.getLevel())) {
                    map.put("level", sysDictDataService.selectDictLabel("zhdd_incident_level", Convert.toStr(incidentVo.getLevel())));
                } else {
                    map.put("level", "-");
                }
            }
            // 查询方案人员
            map.put("incidentPerson", incidentTaskPersonService.listVo(Wrappers.<IncidentTaskPerson>lambdaQuery().eq(IncidentTaskPerson::getIncidentTaskId, id)));
            // 查询方案指令
            List<IncidentTaskCommandVo> incidentTaskCommandVos = incidentTaskCommandService.listVo(Wrappers.<IncidentTaskCommand>lambdaQuery().eq(IncidentTaskCommand::getIncidentTaskId, id));
            for (int i = 0; i < incidentTaskCommandVos.size(); i++) {
                incidentTaskCommandVos.get(i).setIndex(i + 1);
            }
            map.put("incidentCommand", incidentTaskCommandVos);
            // 查询处置过程
            List<IncidentProcess> incidentProcess = iIncidentProcessService.list(Wrappers.<IncidentProcess>lambdaQuery()
                .eq(IncidentProcess::getIncidentId, incidentTaskVo.getIncidentId()).orderByDesc(IncidentProcess::getCreateTime));
            if (incidentProcess != null && incidentProcess.size() > 0) {
                IncidentProcess processData = incidentProcess.get(0);
                map.put("process", DateUtil.formatDateTime(processData.getCreateTime()) + "：" + processData.getDes());
            }
        }
        String fileName = "plan_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".docx";
        try {
            XWPFDocument doc = WordExportUtil.exportWord07(
                "word/incidentTask.docx", map);
            FileOutputStream fos = new FileOutputStream(ExcelUtil.getAbsoluteFile(fileName));
            doc.write(fos);
            // 设置强制下载不打开
            response.setContentType("application/force-download");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            OutputStream out = response.getOutputStream();
            doc.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            delFileWord(ExcelUtil.getAbsoluteFile(fileName));
        }
    }

    /**
     * 删除零时生成的文件
     */
    public static void delFileWord(String filePath) {
        File file = new File(filePath);
        file.delete();
    }

}
