package com.willalp.flow.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.willalp.common.core.domain.DeptOrUserResp;
import com.willalp.common.exception.base.BaseException;
import com.willalp.common.utils.DateUtils;
import com.willalp.common.utils.SecurityUtils;
import com.willalp.common.utils.StringUtils;
import com.willalp.flow.domain.*;
import com.willalp.flow.domain.enums.FlowEnum;
import com.willalp.flow.domain.req.FLowReq;
import com.willalp.flow.mapper.*;
import com.willalp.flow.service.HsFlowEngineService;
import com.willalp.flow.service.IBizLeaveImgService;
import com.willalp.flow.service.IHsFlowConditionModelService;
import com.willalp.flow.service.IHsFlowRunningRecordService;
import com.willalp.msg.domain.HsAppUserMsg;
import com.willalp.msg.service.IHsAppUserMsgService;
import com.willalp.system.domain.HsPostConfig;
import com.willalp.system.domain.vo.PostTreeVo;
import com.willalp.system.service.IHsPostConfigService;
import com.willalp.wx.domain.WxMsgTemplateApproval;
import com.willalp.wx.domain.WxMsgTemplateApprovalResult;
import com.willalp.wx.enums.WxTemplateKeyEnum;
import com.willalp.wx.service.WxMsgService;
import com.willalp.wx.utils.WxUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class HsFlowEngineServiceImpl implements HsFlowEngineService {

    @Resource
    private HsFlowBaseMapper hsFlowBaseMapper;

    @Resource
    private HsFlowExamplesMapper hsFlowExamplesMapper;

    @Resource
    private HsFlowModelMapper hsFlowModelMapper;

    @Resource
    private IHsFlowRunningRecordService flowRunningRecordService;

    @Resource
    private HsFlowTaskMapper hsFlowTaskMapper;

    @Resource
    private HsFlowConditionModelMapper flowConditionModelMapper;

    @Resource
    private IHsFlowConditionModelService conditionModelService;

    @Resource
    private IBizLeaveImgService leaveImgService;

    @Resource
    private WxMsgService wxMsgService;

    @Resource
    private WxUtils wxUtils;

    @Resource
    private IHsAppUserMsgService userMsgService;

    @Resource
    private IHsPostConfigService postConfigService;

    @Override
    public void submitATask(HsFlowTask task, Map<String, String> params) {
        try {
            String examplesId = task.getExamplesId();
            if (StringUtils.isBlank(examplesId)) {
                throw new BaseException("EXAMPLES_ID - IS_NULL");
            }
            HsFlowBase hsFlowBase = hsFlowBaseMapper.firstFlowBase(examplesId);
            if (null == hsFlowBase) {
                throw new BaseException("请创建实例");
            }
            task.setInitiator(SecurityUtils.getUsername());
            task.setBaseId(hsFlowBase.getId());
            task.setTaskName("请假");
            task.setCreateTime(new Date());
            if (ObjectUtils.isNotNull(params)) {
                String userName = params.get("candidate");
                if (StringUtils.isNotBlank(userName)) {
                    task.setOperator(userName);
                }
            }
            hsFlowTaskMapper.insert(task);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("提交失败");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int nextStep(FLowReq flow) {
        if (StringUtils.isBlank(flow.getBaseId())) {
            throw new BaseException("FLOW_BASE_ID - IS_NULL");
        }
        if (StringUtils.isBlank(flow.getTaskId())) {
            throw new BaseException("FLOW_TASK_ID - IS_NULL");
        }
        if (StringUtils.isBlank(flow.getResult())) {
            throw new BaseException("FLOW_TASK_ID - IS_NULL");
        }
        //获取当前基础组件
        HsFlowBase hsFlowBase = hsFlowBaseMapper.selectById(flow.getBaseId());
        if (null == hsFlowBase) {
            throw new BaseException("没有找到组件");
        }
        //获取任务实例
        HsFlowTask hsFlowTask = hsFlowTaskMapper.selectById(flow.getTaskId());
        if (null == hsFlowTask) {
            throw new BaseException("没有找到任务实例");
        }
        if (!SecurityUtils.getUsername().equals(hsFlowTask.getOperator())) {
            throw new BaseException("无操作权限");
        }
        if (FlowEnum.IS_ONE.getValue().equals(hsFlowTask.getIsEnd())) {
            throw new BaseException("任务已经结束");
        }
        String stepId = null;
        //获取是否 是同意结果
        boolean resultTrue = FlowEnum.RESULT_TRUE.getValue().equals(flow.getResult());
        boolean resultCaseOf = FlowEnum.RESULT_CASE_OF.getValue().equals(flow.getResult());
        JSONObject jsonObject = flow.getJsonObject();
        List<HsFlowRunningRecord> list = new ArrayList<>();
        //生成记录
        HsFlowRunningRecord frr = new HsFlowRunningRecord();
        frr.setBaseId(flow.getBaseId());
        frr.setTaskId(flow.getTaskId());
        frr.setCreateTime(new Date());
        if (resultCaseOf) {
            //转交
            hsFlowTask.setOperator(flow.getNextApproval());
            frr.setComment("转交至 " + flow.getNextUserName());
            frr.setOperator(SecurityUtils.getUsername());
            frr.setYesOrNo(flow.getResult());
        } else {
            //查看有无条件组件
            if (StringUtils.isNotBlank(hsFlowBase.getTermModuleId()) &&
                    hsFlowBase.getTermModuleId().contains(FlowEnum.NODE.getValue()) &&
                    null != jsonObject && resultTrue) {
                //遍历绑定的条件组件 查找下一步 （待添加条件级别优化）
                List<HsFlowConditionModel> hsFlowConditionModels = flowConditionModelMapper.queryConditionGroup(hsFlowBase.getUpStepId(), hsFlowBase.getTermModuleId());
                for (HsFlowConditionModel item : hsFlowConditionModels) {
                    String paramName = item.getParamName();
                    if (null != jsonObject.get(paramName)) {
                        if (conditionModelService.executeConditionJudgment(item, jsonObject.get(paramName))) {
                            //获取当前基础组件
                            HsFlowBase newHsFlowBase = hsFlowBaseMapper.selectById(item.getId());
                            stepId = newHsFlowBase.getDownStepId();
                            break;
                        }
                    }
                }
            } else {
                if (resultTrue) {
                    stepId = hsFlowBase.getDownStepId();
                } else {
                    stepId = hsFlowBase.getUpStepId();
                }
            }
            frr.setComment(flow.getComment());
            frr.setOperator(SecurityUtils.getUsername());
            frr.setYesOrNo(flow.getResult());
        }
        list.add(frr);
        if (StringUtils.isNotBlank(stepId)) {
            hsFlowTask.setBaseId(stepId);
            if (StringUtils.isNotBlank(flow.getNextApproval())) {
                frr.setOperator(SecurityUtils.getUsername());
                hsFlowTask.setOperator(flow.getNextApproval());
            } else if (!resultTrue) {
                //拒绝时 通过记录 反向比对 查找上一步 同意的数据并 更新任务
                List<HsFlowRunningRecord> flowRunningRecords = flowRunningRecordService.selectHsFlowRunningRecordTrue(flow.getTaskId());
                int count = 0;
                for (int i = 0; i < flowRunningRecords.size(); i++) {
                    String baseId = flowRunningRecords.get(i).getBaseId();
                    if (StringUtils.isNotBlank(baseId) && StringUtils.equals(baseId, flow.getBaseId())) {
                        hsFlowTask.setBaseId(flowRunningRecords.get(i - 1).getBaseId());
                        hsFlowTask.setOperator(flowRunningRecords.get(i - 1).getOperator());
                        count++;
                        break;
                    }
                }
                //没有找到 默认当前
                if (count == 0) {
                    int i = flowRunningRecords.size() - 1;
                    hsFlowTask.setBaseId(flowRunningRecords.get(i).getBaseId());
                    hsFlowTask.setOperator(flowRunningRecords.get(i).getOperator());
                }
            } else {
                //避免异常找不到任务默认admin
                hsFlowTask.setOperator("admin");
                throw new BaseException("未选择下一步审批人员");
            }

            //判断新组件下一步是否需要选择人员
            HsFlowBase hsFlowBase1 = hsFlowBaseMapper.selectById(stepId);
            if (null != hsFlowBase1 && StringUtils.isBlank(hsFlowBase1.getDownStepId()) &&
                    StringUtils.isBlank(hsFlowBase1.getTermModuleId())) {
                hsFlowTask.setIsCandidate("1");
            } else {
                hsFlowTask.setIsCandidate("0");
            }
        }
        //任务结束
        if (StringUtils.isBlank(stepId) &&
                StringUtils.isBlank(hsFlowBase.getDownStepId()) &&
                !resultCaseOf) {
            hsFlowTask.setBaseId(null);
            hsFlowTask.setOperator(hsFlowTask.getOperator());
            hsFlowTask.setIsEnd("1");
            String businessId = hsFlowTask.getBusinessId();
            if (StringUtils.isNotBlank(businessId)) {
                BizLeaveImg byId = leaveImgService.getById(businessId);
                byId.setRemark("新进度");
                leaveImgService.updateById(byId);
            }
            HsFlowRunningRecord frr1 = new HsFlowRunningRecord();
            frr1.setComment("自动结束");
            frr1.setOperator(SecurityUtils.getUsername());
            frr1.setTaskId(flow.getTaskId());
            frr1.setCreateTime(new Date(new Date().getTime() + 1000));
            list.add(frr1);
            //生成审批结果消息列表
            HsAppUserMsg appUserMsg = new HsAppUserMsg();
            appUserMsg.setMsgContent("您的 [" + jsonObject.get("title") + "] 申请" + (resultTrue ? "已通过" : "已拒绝"));
            appUserMsg.setMsgIsRead("0");
            appUserMsg.setUserCode(String.valueOf(jsonObject.get("apply_user_id")));
            appUserMsg.setMsgType("4");
            appUserMsg.setRemark(hsFlowTask.getId());
            appUserMsg.setCreateTime(new Date());
            userMsgService.save(appUserMsg);

            //推送微信审批结果通知
            WxMsgTemplateApprovalResult wxMsgTemplateApproval = new WxMsgTemplateApprovalResult();
            wxMsgTemplateApproval.setPhrase4(wxUtils.getFormat(resultTrue ? "已通过" : "已拒绝"));
            wxMsgTemplateApproval.setDate3(wxUtils.getFormat(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date())));
            wxMsgTemplateApproval.setThing6(wxUtils.getFormat(String.valueOf(jsonObject.get("title"))));
            wxMsgService.sendQRCodeMsg(String.valueOf(jsonObject.get("apply_user_id")), wxMsgTemplateApproval, WxTemplateKeyEnum.APPROVAL_RESULT, true);
        } else {
            //任务继续
            hsFlowTask.setMsgIsRead("0");
            //生成审批结果消息列表
            HsAppUserMsg appUserMsg = new HsAppUserMsg();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String content = null;
            try {
                content = "<p>标题：" + jsonObject.get("title") + "</p>" +
                        "<p>申请人：" + jsonObject.get("apply_user_name") + "</p>" +
                        "<p>开始时间：" + DateUtils.dateTime(sdf.parse(jsonObject.get("leave_start_time").toString())) + "</p>" +
                        "<p>结束时间：" + DateUtils.dateTime(sdf.parse(jsonObject.get("leave_end_time").toString())) + "</p>";
            } catch (ParseException e) {
                e.printStackTrace();
            }
            appUserMsg.setMsgContent(content);
            appUserMsg.setMsgIsRead("0");
            appUserMsg.setUserCode(hsFlowTask.getOperator());
            appUserMsg.setMsgType("1");
            appUserMsg.setRemark(hsFlowTask.getId());
            appUserMsg.setCreateTime(new Date());
            userMsgService.save(appUserMsg);
            //推送微信待审批通知
            WxMsgTemplateApproval wxMsgTemplateApproval = new WxMsgTemplateApproval();
            wxMsgTemplateApproval.setThing5(wxUtils.getFormat(String.valueOf(jsonObject.get("title"))));
            wxMsgTemplateApproval.setThing11(wxUtils.getFormat(String.valueOf(jsonObject.get("apply_user_name"))));
            wxMsgTemplateApproval.setTime12(wxUtils.getFormat(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date())));
            wxMsgService.sendQRCodeMsg(hsFlowTask.getOperator(), wxMsgTemplateApproval, WxTemplateKeyEnum.APPROVAL_WAIT, true);
        }
        hsFlowTaskMapper.updateById(hsFlowTask);
        flowRunningRecordService.saveBatch(list);
        return 1;
    }

    @Override
    public List<HsFlowTask> getToDoByTaskId(String taskId) {
        if (StringUtils.isBlank(taskId)) {
            return null;
        }
        List<HsFlowTask> hsFlowTasks = hsFlowTaskMapper.selectList(new QueryWrapper<HsFlowTask>()
                .eq("id", taskId));
        return getHsFlowTasks(hsFlowTasks);
    }

    @Override
    public List<HsFlowTask> getToDo(String userCode) {
        if (StringUtils.isBlank(userCode)) {
            return null;
        }
        List<HsFlowTask> hsFlowTasks = hsFlowTaskMapper.selectAllByUserCode(userCode);
        return getHsFlowTasks(hsFlowTasks);
    }

    @Override
    public List<HsFlowTask> getDone(String userCode) {
        if (StringUtils.isBlank(userCode)) {
            return null;
        }
        List<HsFlowTask> hsFlowTasks = hsFlowTaskMapper.getDone(userCode);
        return getHsFlowTasks(hsFlowTasks);
    }

    private List<HsFlowTask> getHsFlowTasks(List<HsFlowTask> hsFlowTasks) {
        if (0 != hsFlowTasks.size()) {
            List<HsFlowExamples> hsFlowExamples = hsFlowExamplesMapper.selectHsFlowExamplesList(null);
            hsFlowTasks.forEach(item -> {
                List<HsFlowExamples> collect = hsFlowExamples.stream().filter(examples -> {
                    if (StringUtils.isNotBlank(examples.getId()) && examples.getId().equals(item.getExamplesId())) {
                        return true;
                    }
                    return false;
                }).collect(Collectors.toList());
                String businessId = item.getBusinessId();
                if (0 != collect.size()) {
                    if (StringUtils.isNotBlank(businessId)) {
                        Map<String, Object> stringObjectMap = hsFlowTaskMapper
                                .selectBusinessCase(collect.get(0).getBusinessTableName(), businessId);
                        if (ObjectUtils.isNotNull(stringObjectMap)) {
                            List<Map<String, Object>> leaveImgs = leaveImgService.getBaseMapper().selectMaps(new QueryWrapper<BizLeaveImg>().eq("biz_leave_id", businessId));
                            stringObjectMap.put("imgUrls", leaveImgs);
                            Set<String> strings = stringObjectMap.keySet();
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                            strings.forEach(str -> {
                                if (StringUtils.isNotBlank(str) && str.contains("time")) {
                                    if (stringObjectMap.get(str) instanceof LocalDateTime) {
                                        stringObjectMap.put(str, formatter.format((LocalDateTime) stringObjectMap.get(str)));
                                    }
                                }
                            });
                            item.formData = new JSONObject(stringObjectMap);
                        }
                    }
                }
            });
        }
        return hsFlowTasks;
    }

    @Override
    public List<HsFlowRunningRecord> currentTaskRecords(String taskId) {
        if (StringUtils.isNotBlank(taskId)) {
            HsFlowRunningRecord hsFlowRunningRecord = new HsFlowRunningRecord();
            hsFlowRunningRecord.setTaskId(taskId);
            return flowRunningRecordService.selectHsFlowRunningRecordList(hsFlowRunningRecord);
        }
        return null;
    }

    @Override
    public int revoke(String taskId) {
        if (StringUtils.isNotBlank(taskId)) {
            long selectCount = flowRunningRecordService.getBaseMapper().selectCount(new QueryWrapper<HsFlowRunningRecord>()
                    .eq("task_id", taskId));
            if (selectCount > 0) {
                throw new BaseException("已有审批结果无法撤销");
            }
            return hsFlowTaskMapper.deleteById(taskId);
        }
        return 0;
    }

    @Override
    public List<PostTreeVo> getTreePost(String taskId) {
        if (StringUtils.isNotBlank(taskId)) {
            HsFlowTask hsFlowTask = hsFlowTaskMapper.selectById(taskId);
            if (null != hsFlowTask) {
                String baseId = hsFlowTask.getBaseId();
                if (StringUtils.isNotBlank(baseId)) {
                    HsFlowBase hsFlowBase = hsFlowBaseMapper.selectById(baseId);
                    if (null != hsFlowBase) {
                        String operator = hsFlowBase.getOperator();
                        if (StringUtils.isNotBlank(operator)) {
                            PostTreeVo postTreeVo = new PostTreeVo();
                            postTreeVo.setText("默认");
                            postTreeVo.setValue("defaultId");
                            List<DeptOrUserResp> deptOrUserResps = JSON.parseArray(operator, DeptOrUserResp.class);
                            List<PostTreeVo> childrens = new ArrayList<PostTreeVo>();
                            if (CollUtil.isNotEmpty(deptOrUserResps)) {
                                for (DeptOrUserResp deptOrUserResp : deptOrUserResps) {
                                    PostTreeVo pv = new PostTreeVo();
                                    pv.setText(deptOrUserResp.getName());
                                    pv.setValue(deptOrUserResp.getId());
                                    childrens.add(pv);
                                }
                            }
                            postTreeVo.setChildren(childrens);
                        }
                    }
                }
            }
        }
        List<HsPostConfig> hsPostConfigs = postConfigService.selectHsPostConfigList(null);
        if (0 != hsPostConfigs.size()) {
            List<PostTreeVo> list = new ArrayList<>();
            String userBS = "AA";
            hsPostConfigs.forEach(item -> {
                PostTreeVo postTreeVo = new PostTreeVo();
                postTreeVo.setText(item.getPostName());
                postTreeVo.setValue(item.getId());
                String postUserG = item.getPostUserG();
                List<PostTreeVo> postTreeCVos = new ArrayList<>();
                if (postUserG != null) {
                    String[] split = postUserG.split(",");
                    for (int i = 0; i < split.length; i++) {
                        PostTreeVo postTreeCVo = new PostTreeVo();
                        String nick;
                        String userId;
                        int of = split[i].indexOf(userBS);
                        if (of != -1) {
                            nick = split[i].substring(0, of);
                            userId = split[i].substring(of);
                        } else {
                            nick = "WILLALP";
                            userId = "admin";
                        }
                        postTreeCVo.setText(nick);
                        postTreeCVo.setValue(userId);
                        postTreeCVos.add(postTreeCVo);
                    }
                }
                postTreeVo.setChildren(postTreeCVos);
                list.add(postTreeVo);
            });
            return list;
        }
        return null;
    }
}
