package com.ruoyi.project.sems.safecheck.controller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.Texts;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.document.ZipUtil;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.project.approve.damain.DevTask;
import com.ruoyi.project.listener.semsWeekCheck.SafeDirTaskCreateListener;
import com.ruoyi.project.listener.semsWeekCheck.WeekcheckEndFailListener;
import com.ruoyi.project.listener.semsWeekCheck.WeekcheckEndSuccessListener;
import com.ruoyi.project.officeConvert.OfficeConvertController;
import com.ruoyi.project.sems.safecheck.mapper.TSpecWeekcheckMapper;
import com.ruoyi.project.system.domain.SysConfig;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysConfigMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.system.service.ISysUserService;
import io.jsonwebtoken.lang.Assert;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.project.sems.safecheck.domain.TSpecWeekcheck;
import com.ruoyi.project.sems.safecheck.service.ITSpecWeekcheckService;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.page.TableDataInfo;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 每周安全排查Controller
 *
 * @author Li
 * @date 2023-08-21
 */
@RestController
@RequestMapping("/safecheck/weekcheck")
public class TSpecWeekcheckController extends BaseController
{
    @Autowired
    private ITSpecWeekcheckService tSpecWeekcheckService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private OfficeConvertController officeConvertController;
    @Resource
    private SysConfigMapper configMapper;
    @Resource
    private SysUserMapper userMapper;
    @Resource
    private TSpecWeekcheckMapper tSpecWeekcheckMapper;

    /**
     * 查询每周安全排查列表
     */
    @PreAuthorize("@ss.hasPermi('safecheck:weekcheck:list')")
    @GetMapping("/list")
    public TableDataInfo list(TSpecWeekcheck tSpecWeekcheck)
    {
        startPage();
        List<TSpecWeekcheck> list = tSpecWeekcheckService.selectTSpecWeekcheckList(tSpecWeekcheck);
        return getDataTable(list);
    }

    /**
     * 根据参数键名查询政府回执
     */
    @GetMapping(value = "/getSafeDirUserId")
    public AjaxResult getSafeDirUserId()
    {
        SysConfig config = new SysConfig();
        config.setConfigKey("sems.weekchek.safedir");
        SysConfig retConfig = configMapper.selectConfig(config);
        SysUser sysUser =  userMapper.selectUserByStaffId(retConfig.getConfigValue());
        return AjaxResult.success(sysUser.getUserId());
    }

    /**
     * 导出每周安全排查列表
     */
    @PreAuthorize("@ss.hasPermi('safecheck:weekcheck:export')")
    @Log(title = "每周安全排查", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult export(TSpecWeekcheck tSpecWeekcheck)
    {
        List<TSpecWeekcheck> list = tSpecWeekcheckService.selectTSpecWeekcheckList(tSpecWeekcheck);
        ExcelUtil<TSpecWeekcheck> util = new ExcelUtil<TSpecWeekcheck>(TSpecWeekcheck.class);
        return util.exportExcel(list, "weekcheck");
    }

    /**
     * 获取每周安全排查详细信息
     */
    @PreAuthorize("@ss.hasPermi('safecheck:weekcheck:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(tSpecWeekcheckService.selectTSpecWeekcheckById(id));
    }

    /**
     * 新增每周安全排查
     */
    @PreAuthorize("@ss.hasPermi('safecheck:weekcheck:add')")
    @Log(title = "每周安全排查", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TSpecWeekcheck tSpecWeekcheck)
    {
        long userId = getUserId();
        tSpecWeekcheck.setCreaterCode(userId);
        tSpecWeekcheck.setSafeAdminId(String.valueOf(userId));
        tSpecWeekcheck.setSafeAdminDate(tSpecWeekcheck.getCheckDate());

        SysUser admin = sysUserService.selectUserById(Long.valueOf(tSpecWeekcheck.getSafeAdminId()));
        tSpecWeekcheck.setSafeAdminName(admin.getNickName());
        SysUser dir = sysUserService.selectUserById(Long.valueOf(tSpecWeekcheck.getSafeDirId()));
        tSpecWeekcheck.setSafeDirName(dir.getNickName());

        tSpecWeekcheckService.insertTSpecWeekcheck(tSpecWeekcheck);
        //开始工作流、监听
        Map<String, Object> variables = new HashMap<>();

        variables.put("safeDir", tSpecWeekcheck.getSafeDirId());

        variables.put("safeDirTaskCreateListener", new SafeDirTaskCreateListener());
        variables.put("weekcheckEndFailListener", new WeekcheckEndFailListener());
        variables.put("weekcheckEndSuccessListener", new WeekcheckEndSuccessListener());

        Long userid = getUserId();
        Authentication.setAuthenticatedUserId(userid.toString());
        //采用key来启动流程定义并设置流程变量，返回流程实例
        ProcessInstance pi = runtimeService.startProcessInstanceByKey("semsWeekcheck", String.valueOf(tSpecWeekcheck.getId()), variables);
        logger.info("流程部署id：" + pi.getDeploymentId());
        logger.info("流程定义id：" + pi.getProcessDefinitionId());
        logger.info("流程实例id：" + pi.getProcessInstanceId());
        tSpecWeekcheck.setPlantCode(pi.getProcessInstanceId());
        tSpecWeekcheckService.updateTSpecWeekcheck(tSpecWeekcheck);
        return AjaxResult.success();
    }

    /**
     * 修改每周安全排查
     */
    @PreAuthorize("@ss.hasPermi('safecheck:weekcheck:edit')")
    @Log(title = "每周安全排查", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TSpecWeekcheck tSpecWeekcheck)
    {
        long userId = getUserId();
        tSpecWeekcheck.setCreaterCode(userId);
        tSpecWeekcheck.setSafeAdminId(String.valueOf(userId));
        tSpecWeekcheck.setSafeAdminDate(tSpecWeekcheck.getCheckDate());
        SysUser admin = sysUserService.selectUserById(Long.valueOf(tSpecWeekcheck.getSafeAdminId()));
        tSpecWeekcheck.setSafeAdminName(admin.getNickName());
        return toAjax(tSpecWeekcheckService.updateTSpecWeekcheck(tSpecWeekcheck));
    }

    /**
     * 删除每周安全排查
     */
    @PreAuthorize("@ss.hasPermi('safecheck:weekcheck:remove')")
    @Log(title = "每周安全排查", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(tSpecWeekcheckService.deleteTSpecWeekcheckByIds(ids));
    }

    /**
     * 作废每周安全排查
     */
    @PreAuthorize("@ss.hasPermi('safecheck:weekcheck:remove')")
    @Log(title = "作废每周安全排查", businessType = BusinessType.DELETE)
    @DeleteMapping("/cancel/{id}")
    public AjaxResult cancel(@PathVariable Long id)
    {
        return toAjax(tSpecWeekcheckMapper.cancelTSpecWeekcheckByIds(id));
    }

    /**
     * @return
     * @throws IOException
     */
    @RequestMapping("/downloadWeekcheck")
    public AjaxResult downloadDailycheck(@RequestParam String id, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String[] ids = id.split(",");
        OutputStream out = null;
        out = response.getOutputStream();
        //存放所有文件路径
        List<String> list = new ArrayList<>();
        for (int i = 0; i < ids.length; i++) {
            String url = PreView(Long.parseLong(ids[i]));
            // 将路径字符串转换为Path对象
            Path path = Paths.get(url);
            // 获取文件名
            String fileName = path.getFileName().toString();
            list.add(fileName);
        }
        logger.info(JSON.toJSONString(list));
        return ZipUtil.createZip(RuoYiConfig.getProfile() + "/sems/weekcheck/", "",  "每周安全检查报告.zip", list, response);
    }

    /**
     * @return
     * @throws IOException
     */
    @RequestMapping("/downloadWeekcheckPdf")
    public AjaxResult downloadWeekcheckPdf(@RequestParam String id, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String[] ids = id.split(",");
        OutputStream out = null;
        out = response.getOutputStream();
        //存放所有文件路径
        List<String> list = new ArrayList<>();
        for (int i = 0; i < ids.length; i++) {
            String url = PreView(Long.parseLong(ids[i]));
            // 将路径字符串转换为Path对象
            Path path = Paths.get(url);
            // 获取文件名
            String fileName = path.getFileName().toString();
            fileName = officeConvertController.wordTransPdf(url);
            String newFilePath=fileName.replace("/profile","");
            logger.info("fileName:" + newFilePath);
            list.add(newFilePath);
        }
        logger.info(JSON.toJSONString(list));
        return ZipUtil.createZip(RuoYiConfig.getProfile() + "", "",  "每周安全检查报告PDF版.zip", list, response);
    }

    /**
     * @param id
     * @return
     * @throws IOException
     */
    @GetMapping("/wordView/{id}")
    public AjaxResult wordView(@PathVariable Long id) throws IOException {
        //根据ID查询并生成
        String url = PreView(id);
        return AjaxResult.success(url);
    }


    /**
     * @param id 生成文件名
     * @return
     * @throws IOException
     */
    public String PreView(Long id) throws IOException {
        //根据ID查询并生成
        TSpecWeekcheck t = tSpecWeekcheckService.selectTSpecWeekcheckById(id);
        String url = this.createcheck(t);
        return url;
    }

    /**
     * 生成wordt
     */
    public String createcheck(TSpecWeekcheck tSpecWeekcheck) throws IOException {
        //生成word
        //渲染文本
        Map<String, Object> params = getWordData(tSpecWeekcheck);
        // 模板路径
        String templatePath = "static/word/sems/check/weekcheck.docx";
        // 生成word的路径
        String fileDir = RuoYiConfig.getProfile() + "/" + "sems/weekcheck";
        // 生成word的文件名称
        String fileName =DateUtils.parseDateToStr("YYYY",tSpecWeekcheck.getCheckDate()) + "第" +tSpecWeekcheck.getWeekNo()+ "周" +"_" +tSpecWeekcheck.getId()  + ".docx";
        String wordPath = this.createWord(templatePath, fileDir, fileName, params);
        return wordPath;
    }

    /**
     * 获取word数据
     */
    public Map<String, Object> getWordData(TSpecWeekcheck tSpecWeekcheck) {
        Map<String, Object> params = new HashMap<>();

        params.put("checkDate", Texts.of(DateUtils.dateTime(tSpecWeekcheck.getCheckDate())).fontSize(10).bold().create());
        params.put("weekNo", Texts.of(tSpecWeekcheck.getWeekNo()).fontSize(10).bold().create());
        params.put("lastWeekRisk", Texts.of(tSpecWeekcheck.getLastWeekRisk()).fontSize(10).bold().create());
        params.put("thisWeekRisk", Texts.of(tSpecWeekcheck.getThisWeekRisk()).fontSize(10).bold().create());
        params.put("safeCondition", Texts.of(tSpecWeekcheck.getSafeCondition()).fontSize(10).bold().create());
        params.put("nextWeekWork", Texts.of(tSpecWeekcheck.getNextWeekWork()).fontSize(10).bold().create());
        params.put("safeAdminSug", Texts.of(tSpecWeekcheck.getSafeAdminSug()).fontSize(10).bold().create());
        params.put("safeDirSug", Texts.of(tSpecWeekcheck.getSafeDirSug()).fontSize(10).bold().create());
        SysUser safeAdmin = userService.selectUserById(Long.parseLong(tSpecWeekcheck.getSafeAdminId()));
        if (safeAdmin.getSignUrl() != null && new File(fileName(safeAdmin.getSignUrl())).exists()) {
            params.put("safeAdminP", Pictures.ofLocal(fileName(safeAdmin.getSignUrl())).size(80, 40).create());
        } else {
            params.put("safeAdmin", Texts.of(safeAdmin.getNickName()).fontSize(10).bold().create());
        }
        if (tSpecWeekcheck.getSafeAdminDate() != null) {
            params.put("safeAdminDate", Texts.of(DateUtils.dateTime(tSpecWeekcheck.getSafeAdminDate())).fontSize(11).bold().create());

        }

        SysUser safeDir = userService.selectUserById(Long.parseLong(tSpecWeekcheck.getSafeDirId()));
        if (safeDir.getSignUrl() != null && new File(fileName(safeDir.getSignUrl())).exists()) {
            params.put("safeDirP", Pictures.ofLocal(fileName(safeDir.getSignUrl())).size(80, 40).create());
        } else {
            params.put("safeDir", Texts.of(safeDir.getNickName()).fontSize(10).bold().create());
        }
        if (tSpecWeekcheck.getSafeDirDate() != null) {
            params.put("safeDirDate", Texts.of(DateUtils.dateTime(tSpecWeekcheck.getSafeDirDate())).fontSize(11).bold().create());

        }

        // 渲染文本
        return params;
    }

    /**
     * @param templatePath word模板文件路径
     * @param fileDir      生成的文件存放地址
     * @param fileName     生成的文件名
     * @param paramMap     参数集合
     * @return 返回word生成的路径
     */
    public String createWord(String templatePath, String fileDir, String fileName, Map<String, Object> paramMap) throws IOException {
        Assert.notNull(templatePath, "word模板文件路径不能为空");
        Assert.notNull(fileDir, "生成的文件存放地址不能为空");
        Assert.notNull(fileName, "生成的文件名不能为空");
        File dir = new File(fileDir);
        if (!dir.exists()) {
            logger.info("目录不存在，创建文件夹{}!", fileDir);
            dir.mkdirs();
        }
        fileName = fileName.replaceAll("/", "_"); //替换文件中敏感字段
        logger.info("目录文件{}!", fileName);
        String filePath = fileDir + "/" + fileName;
        logger.info("目录{}!", filePath);
        // 读取模板渲染参数
        InputStream is = getClass().getClassLoader().getResourceAsStream(templatePath);
        XWPFTemplate template = XWPFTemplate.compile(is).render(paramMap);
        try {
            // 将模板参数写入路径
            template.writeToFile(filePath);
            template.close();
        } catch (Exception e) {
            logger.error("生成word异常{}", e.getMessage());
            e.printStackTrace();
        }
        String pathFileName = FileUploadUtils.getPathFileName(RuoYiConfig.getFilePath("/" + "sems/weekcheck"), fileName);
        return pathFileName;
    }

    /**
     * @param
     * @return 映射签名的文件名
     * @throws IOException
     */
    public String fileName(String filepath) {
        String newFilePath = filepath.replace("/profile", "");
        String pathName = RuoYiConfig.getProfile() + newFilePath;
        return pathName;
    }

    /**
     * 审核处理
     */
    @Log(title = "特种设备审核处理", businessType = BusinessType.UPDATE)
    @PutMapping("/handle")
    public AjaxResult handle(@RequestBody DevTask devTask) {
        //使用任务服务完成任务(提交任务)
        String taskId = devTask.getTaskId();
        // 使用任务id,获取任务对象，获取流程实例id
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //利用任务对象，获取流程实例id
        String processInstancesId = task.getProcessInstanceId();

        Map<String, Object> param = new HashMap<>();
        param.put("condition", devTask.getCondition());

        String taskName = task.getName();//实例名
        if (taskName.equals("安全总监")) {
            String jsonString = JSON.toJSONString(devTask.getApproveObject()) ;
            // 将JSON字符串转换为TSpecWeekcheck对象
            TSpecWeekcheck weekcheck = JSON.parseObject(jsonString, TSpecWeekcheck.class);
            weekcheck.setSafeDirDate(weekcheck.getCheckDate());
            tSpecWeekcheckService.updateTSpecWeekcheck(weekcheck);
        }
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        //认领任务
        processEngine.getTaskService()//
                .claim(taskId, getUserId().toString());
//        Authentication.setAuthenticatedUserId("cmc"); // 添加批注时候的审核人
        taskService.addComment(taskId, processInstancesId, devTask.getComment());
        //业务监听处理
//        tApproveService.handleApprove(task ,devTask);
        taskService.complete(taskId, param);
        return AjaxResult.success();
    }
}
