package com.gyee.frame.service.impl.ticket;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gyee.frame.common.exception.TicketException;
import com.gyee.frame.model.ticket.*;
import com.gyee.frame.mapper.ticket.WfinstanceMapper;
import com.gyee.frame.service.ticket.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gyee.frame.util.DateUtils;
import com.gyee.frame.util.ticket.TicketUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author chenmh
 * @since 2020-07-21
 */
@Service
public class WfinstanceServiceImpl extends ServiceImpl<WfinstanceMapper, Wfinstance> implements WfinstanceService {

    @Autowired
    WftransService wftransService;
    @Autowired
    WfnodeService wfnodeService;
    @Autowired
    WfassignmentService wfassignmentService;
    @Autowired
    LaborService laborService;
    @Autowired
    WfprocessService wfprocessService;
    @Autowired
    WfactionService wfactionService;
    @Autowired
    WorkticketService workticketService;
    @Autowired
    WftaskassignService wftaskassignService;


    @Override
    public int selectMaxId() {
        return baseMapper.selectMaxId();
    }

    /**
     * map的status属性  0：未开始  1：结束  2：正在进行
     *
     * @param ownerId
     * @return
     */
    @Override
    public Map<String, Object> flowInstance(double ownerId) {
        QueryWrapper<Wfinstance> wrapper = new QueryWrapper<>();
        wrapper.eq("OWNERID", ownerId);
        Wfinstance wfinstance = baseMapper.selectOne(wrapper);

        /**
         * 返回结果 -- map
         */
        Map<String, Object> map = new HashMap<>();
        List<FlowStep> list = new ArrayList<>();

        if (wfinstance == null) {
            map.put("flow", list);
            map.put("status", "0");
            return map;
        }

        /**
         * 人员： num ===> name
         */
        List<Labor> labors = laborService.getLabors();
        Map<String, String> laborMap = new HashMap<>();
        for (Labor labor : labors){
            laborMap.put(labor.getLabornum().toLowerCase(), labor.getLaborname());
        }

        /**
         * 查询流程相关历史
         */
        List<Wftrans> wftrans = wftransService.listTrans(wfinstance.getId());
        List<Wfnode> wfnodes = wfnodeService.getListNodes(wfinstance.getWfname(), wfinstance.getWfrevision());

        Map<Double, String> nodeMap = wfnodes.stream().collect(Collectors.toMap(Wfnode::getId, Wfnode::getTitle));

        for (int i = 0; i < wftrans.size(); i++) {
            FlowStep obj = null;
            switch (wftrans.get(i).getNodetype()) {
                case "开始":
                    obj = new FlowStep("节点：" + nodeMap.get(wftrans.get(i).getNodeid()),
                            "人员：" + laborMap.get(wfinstance.getStartor().toLowerCase()),
                            "日期：" + DateUtils.format(wftrans.get(i).getTransdate(), DateUtils.DATE_TIME_PATTERN));
                    break;
                case "任务":
                    obj = new FlowStep("节点：" + nodeMap.get(wftrans.get(i).getNodeid()),
                            "人员：" + laborMap.get(wftrans.get(i).getAssigncode().toLowerCase()),
                            "日期：" + DateUtils.format(wftrans.get(i).getTransdate(), DateUtils.DATE_TIME_PATTERN));
                    break;
                case "结束":
                    obj = new FlowStep("节点：" + nodeMap.get(wftrans.get(i).getNodeid()));
                    break;
            }
            list.add(obj);
        }

        /**
         * 如果active值为‘否’，表示流程已经结束
         */
        if (wfinstance.getActive().equals("否")) {
            map.put("flow", list);
            map.put("status", "1");
            return map;
        }

        /**
         * 如果active值为‘是’，表示流程正在进行
         */
        if (wfinstance.getActive().equals("是")) {
            // 添加最后一条待办信息
            List<Wfassignment> items = wfassignmentService.getActiveItem(wfinstance.getId(), wfinstance.getWfrevision(), wfinstance.getOwnerid(), "活动");
            String labor = "";
            for (int i = 0; i < items.size(); i++){
                String code = laborMap.get(items.get(i).getAssigncode().toLowerCase());
                labor = labor + " " + code;
            }
            FlowStep obj = new FlowStep("节点：" + nodeMap.get(items.get(0).getNodeid()),
                    "人员：" + labor,
                    "日期：");
            list.add(obj);
            map.put("flow", list);
            map.put("status", 2);
            map.put("nodeid", items.get(0).getNodeid());
            map.put("version", wfinstance.getWfrevision());
            map.put("instid", wfinstance.getId());
        }

        return map;
    }

    @Override
    public Wfinstance instance(double ownerId) {
        QueryWrapper<Wfinstance> wrapper = new QueryWrapper<>();
        wrapper.eq("OWNERID", ownerId);
        Wfinstance wfinstance = baseMapper.selectOne(wrapper);

        return wfinstance;
    }

    @Transactional
    @Override
    public boolean initInstance(double ownerId, String wfName, String ticketNum, String principal, String stater, List<String> labor, String role, String online) {
        // 如果在线人员不是工作负责人，则不可启动流程
        if (!online.equals(principal))
            throw new TicketException("只有工作票负责人可以启动流程");

        QueryWrapper<Wfinstance> wrapper = new QueryWrapper<>();
        wrapper.eq("OWNERID", ownerId);
        List<Wfinstance> wfinstances = baseMapper.selectList(wrapper);
        // 判断流程是否已经开始
        if (wfinstances != null && wfinstances.size() > 0)
            return false;

        Wfprocess process = wfprocessService.activeVersion(wfName);
        Wfaction action = wfactionService.initAction(wfName);
        if (process == null || action == null)
            throw new RuntimeException();

        // 生成描述
        String description = process.getWfinstdesc();
        description = description.replace(":{ticketnum}", ticketNum);

        if (wfName.contains("动火")){
            description = description.replace(":{fireprincipal}", principal);
        } else {
            description = description.replace(":{principal}", principal);
        }

        int id = selectMaxId();
        Wfinstance instance = new Wfinstance();
        instance.setId((double)id + 1);
        instance.setWfname(wfName);
        instance.setWfrevision(process.getWfrevision());
        instance.setOwnertable(process.getTablename());
        instance.setOwnerid(ownerId);
        instance.setActive("是");
        instance.setStartor(stater);
        instance.setStarttime(new Date());
        instance.setCurnodeid(action.getEndnodeid());
        instance.setDescription(description);

        int insert = baseMapper.insert(instance);
        if (insert <= 0)
            throw new RuntimeException();

        Wftaskassign task= wftaskassignService.taskAssign(action.getEndnodeid(), process.getWfrevision(), wfName);
        for (int i = 0; i < labor.size(); i++){
            Wfassignment assignment = new Wfassignment();
            assignment.setDescription(task.getDescription().replace(":{TICKETNUM}", ticketNum));
            assignment.setId((double)wfassignmentService.selectMaxId() + 1);
            assignment.setAssigncode(labor.get(i));
            assignment.setApp(TicketUtil.wfNameFormat(wfName));
            assignment.setStartdate(new Date());
            assignment.setEmailnotify("否");
            assignment.setAssignstatus("活动");
            assignment.setWfinstid((double)id + 1);
            assignment.setWfname(wfName);
            assignment.setWfrevision(process.getWfrevision());
            assignment.setInitperson("");
            assignment.setOwnertable(process.getTablename());
            assignment.setOwnerid(ownerId);
            assignment.setInitperson(stater);
            assignment.setWfrole(role);
            assignment.setDealtimeout(0.0);
            assignment.setDealtype("0");
            assignment.setDealtype("自动发送");
            assignment.setPriority(0.0);
            assignment.setEnddate(null);
            assignment.setNodeid(action.getEndnodeid());
            assignment.setTaskid(task.getId());
            assignment.setNeedpass("否");

            boolean save = wfassignmentService.save(assignment);
            if(!save)
                throw new RuntimeException();
        }

        Wftrans trans = new Wftrans();
        trans.setId((double)wftransService.selectMaxId() + 1);
        trans.setNodeid(action.getStartnodeid());
        trans.setWfinstid((double)id + 1);
        trans.setAssignid(null);
        trans.setActionid(action.getId());
        trans.setTranstype("开始");
        trans.setTransdate(new Date());
        trans.setMemo(null);
        trans.setNodetype("开始");
        trans.setWfname(wfName);
        trans.setWfrevision(process.getWfrevision());
        trans.setOwnertable(process.getTablename());
        trans.setOwnerid(ownerId);
        // TODO
        // 根据当前登录角色添加
        trans.setAssigncode(stater);
        trans.setPriority(Double.valueOf(0));

        boolean result = wftransService.save(trans);
        if(!result)
            throw new RuntimeException();

        // 更新票据状态
        boolean update = workticketService.updateTicket(ownerId, action.getStartnodeid(), action.getEndnodeid());
        if (!update)
            return false;

        return true;
    }

    @Transactional
    @Override
    public boolean updateInstance(double id, double nodeId, String active) {
        Wfinstance instance = new Wfinstance();
        instance.setId(id);
        instance.setCurnodeid(nodeId);
        if (active != null)
            instance.setActive(active);

        int i = baseMapper.updateById(instance);
        if (i <= 0)
            throw new RuntimeException();

        return true;
    }
}
