package com.ruoyi.system.service.impl;

import java.io.OutputStream;
import java.io.StringReader;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.entity.BpmProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.BpmProcessMapper;
import com.ruoyi.system.service.IBpmProcessService;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

/**
 * 流程定义Service业务层处理
 *
 * @author hzh
 * @date 2023-10-10
 */
@Service
public class BpmProcessServiceImpl implements IBpmProcessService {
    @Autowired
    private BpmProcessMapper bpmProcessMapper;

    /**
     * 查询流程定义
     *
     * @param processId 流程定义主键
     * @return 流程定义
     */
    @Override
    public BpmProcess selectBpmProcessByProcessId(Long processId) {
        return bpmProcessMapper.selectBpmProcessByProcessId(processId);
    }

    /**
     * 查询流程定义列表
     *
     * @param bpmProcess 流程定义
     * @return 流程定义
     */
    @Override
    public List<BpmProcess> selectBpmProcessList(BpmProcess bpmProcess) {
        return bpmProcessMapper.selectBpmProcessList(bpmProcess);
    }

    /**
     * 新增流程定义
     *
     * @param bpmProcess 流程定义
     * @return 结果
     */
    @Override
    public int insertBpmProcess(BpmProcess bpmProcess) {
        // 解析到字节流中的xml内容进行存储
        byte[] decodedBytes = Base64.getDecoder().decode(bpmProcess.getProcessXml().split("data:text/xml;base64,")[1]);
        String decodedString = new String(decodedBytes);
        // 存储标签内容
        bpmProcess.setProcessXmlContent(decodedString);
        bpmProcess.setCreateTime(DateUtils.getNowDate());
        bpmProcess.setCreateBy(SecurityUtils.getUsername());
        bpmProcess.setProcessVersion(0L);

        System.err.println(bpmProcess.getProcessXmlContent().getBytes(StandardCharsets.UTF_8).toString());

        return bpmProcessMapper.insertBpmProcess(bpmProcess);
    }

    /**
     * 修改流程定义
     *
     * @param bpmProcess 流程定义
     * @return 结果
     */
    @Override
    public int updateBpmProcess(BpmProcess bpmProcess) {
        bpmProcess.setUpdateTime(DateUtils.getNowDate());
        bpmProcess.setUpdateBy(SecurityUtils.getUsername());
        return bpmProcessMapper.updateBpmProcess(bpmProcess);
    }

    /**
     * 批量删除流程定义
     *
     * @param processIds 需要删除的流程定义主键
     * @return 结果
     */
    @Override
    public int deleteBpmProcessByProcessIds(Long[] processIds) {
        return bpmProcessMapper.deleteBpmProcessByProcessIds(processIds);
    }

    /**
     * 删除流程定义信息
     *
     * @param processId 流程定义主键
     * @return 结果
     */
    @Override
    public int deleteBpmProcessByProcessId(Long processId) {
        return bpmProcessMapper.deleteBpmProcessByProcessId(processId);
    }

    /**
     * 备份
     * 需要实现历史版本功能 每次进行修改时就是一次版本的更新
     * 备份可以导出xml文件理论上实现复制流程
     *
     * @param bpmProcess
     * @return
     */
    @Override
    public int bpmBackups(BpmProcess bpmProcess) {
        bpmProcess = bpmProcessMapper.selectBpmProcessByProcessId(bpmProcess.getProcessId());
        bpmProcess.setCreateTime(DateUtils.getNowDate());
        bpmProcess.setCreateBy(SecurityUtils.getUsername());
        bpmProcess.setProcessVersion(1L);  // 设置为历史版本，备份状态
        return bpmProcessMapper.insertBpmProcess(bpmProcess);
    }

    @Override
    public void export(Long processId,String fileType, HttpServletRequest request, HttpServletResponse response) {
        BpmProcess process = bpmProcessMapper.selectBpmProcessByProcessId(processId);
        String fileName = process.getProcessName()+"."+fileType;
        try {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(new InputSource(new StringReader(process.getProcessXmlContent())));
            // 规范化XML结构
            doc.getDocumentElement().normalize();
            // 创建转换器以生成XML
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            DOMSource source = new DOMSource(doc);
            // 创建输出流，将XML写入响应
            OutputStream outputStream = response.getOutputStream();
            response.setContentType("application/xml");
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
            response.setHeader("Content-Disposition", "attachment; filename="+encodedFileName);
            // 将XML写入响应输出流
            StreamResult result = new StreamResult(outputStream);
            transformer.transform(source, result);
            System.out.println("XML file downloaded");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
