package org.jeecg.modules.flowable.controller;

import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.repository.ProcessDefinition;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.flowable.apithird.business.entity.SysExpression;
import org.jeecg.modules.flowable.apithird.business.service.ISysExpressionService;
import org.jeecg.modules.flowable.apithird.entity.SysCategory;
import org.jeecg.modules.flowable.apithird.entity.SysRole;
import org.jeecg.modules.flowable.apithird.entity.SysUser;
import org.jeecg.modules.flowable.apithird.service.IFlowThirdService;
import org.jeecg.modules.flowable.domain.dto.FlowProcDefDto;
import org.jeecg.modules.flowable.domain.dto.FlowSaveXmlVo;
import org.jeecg.modules.flowable.service.IFlowDefinitionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 工作流程定义
 * </p>
 *
 */
@Slf4j
@RestController
@RequestMapping("/flowable/definition")
public class FlowDefinitionController {

    @Autowired
    private IFlowDefinitionService flowDefinitionService;

    @Autowired
    private IFlowThirdService iFlowThirdService;

    @Autowired
    private ISysExpressionService sysExpressionService;

    @GetMapping(value = "/list")
    public Result list(@RequestParam Integer pageNum, @RequestParam Integer pageSize, FlowProcDefDto flowProcDefDto
    ) {
        return Result.OK(flowDefinitionService.list(pageNum, pageSize,flowProcDefDto));
    }

    @PostMapping("/import")
    public Result importFile(@RequestParam(required = false) String name,
                                 @RequestParam(required = false) String category,
                                 MultipartFile file) {
        InputStream in = null;
        try {
            in = file.getInputStream();
            flowDefinitionService.importFile(name, category, in);
        } catch (Exception e) {
            log.error("导入失败:", e);
            return Result.OK(e.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                log.error("关闭输入流出错", e);
            }
        }

        return Result.OK("导入成功");
    }

    @GetMapping("/readXml")
    public Result readXml(@RequestParam(value = "deployId") String deployId) {
        try {
            return flowDefinitionService.readXml(deployId);
        } catch (Exception e) {
            return Result.error("加载xml文件异常");
        }

    }

    @GetMapping("/readXmlByDataId")
    public Result readXmlByDataId(@RequestParam(value = "dataId") String dataId) {
        try {
            return flowDefinitionService.readXmlByDataId(dataId);
        } catch (Exception e) {
            return Result.error("加载xml文件异常");
        }

    }

    @GetMapping("/readImage")
    public void readImage(@RequestParam(value = "deployId") String deployId, HttpServletResponse response) {
        OutputStream os = null;
        BufferedImage image = null;
        try {
            image = ImageIO.read(flowDefinitionService.readImage(deployId));
            response.setContentType("image/png");
            os = response.getOutputStream();
            if (image != null) {
                ImageIO.write(image, "png", os);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @GetMapping("/readImageByDataId")
    public void readImageByDataId(@RequestParam(value = "dataId") String dataId, HttpServletResponse response) {
        OutputStream os = null;
        BufferedImage image = null;
        try {
            image = ImageIO.read(flowDefinitionService.readImageByDataId(dataId));
            response.setContentType("image/png");
            os = response.getOutputStream();
            if (image != null) {
                ImageIO.write(image, "png", os);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @PostMapping("/save")
    public Result save(@RequestBody FlowSaveXmlVo vo) {
        InputStream in = null;
        try {
            in = new ByteArrayInputStream(vo.getXml().getBytes(StandardCharsets.UTF_8));
            ProcessDefinition deploy= flowDefinitionService.importFile(vo.getName(), vo.getCategory(), in);
            flowDefinitionService.updateState(2, deploy.getDeploymentId());
        } catch (Exception e) {
            log.error("导入失败:", e);
            return Result.OK(e.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                log.error("关闭输入流出错", e);
            }
        }

        return Result.OK("导入成功");
    }

    @PostMapping("/startByProcDefId")
    public Result startByProcDefId(
            @RequestBody Map<String, Object> variables) {
        String procDefId = variables.get("procDefId").toString();
        return flowDefinitionService.startProcessInstanceById(procDefId, variables);

    }

    @PostMapping("/startByProcDefKey")
    public Result startByProcDefKey(
                        @RequestBody Map<String, Object> variables) {
        String procDefKey = variables.get("procDefKey").toString();
        return flowDefinitionService.startProcessInstanceByKey(procDefKey, variables);

    }
    @PostMapping("/startByDataId")
    public Result startByDataId(@RequestBody Map<String, Object> variables) {
        String dataId = variables.get("dataId").toString();
        return flowDefinitionService.startProcessInstanceByDataId(dataId, variables);

    }

    @PutMapping(value = "/updateState")
    public Result updateState(
            @RequestParam Integer state,
            @RequestParam String deployId) {
        flowDefinitionService.updateState(state, deployId);
        return Result.OK("操作成功");
    }

    @DeleteMapping(value = "/delete")
    public Result delete( @RequestParam String deployId) {
        flowDefinitionService.delete(deployId);
        return Result.OK();
    }

    @DeleteMapping(value = "/batchDelete")
    public Result<String> batchDelete(@RequestParam(name="ids",required=true) String ids) {
        List<String> idsList = Arrays.asList(ids.split(","));
        for(String id :idsList) {
            flowDefinitionService.delete(id);
        }
        return Result.OK("批量删除成功!");
    }

    @GetMapping("/userList")
    public Result userList(SysUser user) {
        List<SysUser> list = iFlowThirdService.getAllUser();
        return Result.OK(list);
    }

    @GetMapping("/roleList")
    public Result roleList(SysRole role) {
        List<SysRole> list = iFlowThirdService.getAllRole();
        return Result.OK(list);
    }

    @GetMapping("/categoryList")
    public Result categoryList(SysCategory category) {
        List<SysCategory> list = iFlowThirdService.getAllCategory();
        return Result.OK(list);
    }

    @GetMapping("/selectTableNameList")
    public Result selectTableNameList( ) {
        List<SysCategory> arylist= new ArrayList<>();
        List<SysExpression> list = sysExpressionService.selectTableNameList();
        for(int i=0;i<list.size();i++){
            SysExpression seb=list.get(i);
            SysCategory scb=new SysCategory();
            scb.setName(seb.getName());
            arylist.add(scb);
        }
        return Result.OK(arylist);
    }

    @PostMapping("/startByDeployId")
    public Result startByDeployId(@RequestBody Map<String, Object> variables) {
        String deployId = variables.get("deployId").toString();
        return flowDefinitionService.startProcessInstanceByDeployId(deployId, variables);
    }

}
