/*
 * Copyright (c) 2023 codvision.com All Rights Reserved.
 */

package com.codvision.workflow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.codvision.commoncore.utils.Preconditions;
import com.codvision.webcore.bean.QueryPage;
import com.codvision.workflow.entity.WorkFlowButton;
import com.codvision.workflow.mapper.WorkFlowButtonMapper;
import com.codvision.workflow.service.WorkFlowButtonService;
import com.codvision.workflow.util.WorkFlowUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static com.codvision.workflow.constant.WorkFlowConstant.*;

/**
 * @author hxl
 */
@Service
@RequiredArgsConstructor
public class WorkFlowButtonServiceImpl extends ServiceImpl<WorkFlowButtonMapper, WorkFlowButton> implements WorkFlowButtonService {

    private final TaskService taskService;
    private final RepositoryService repositoryService;

    @Override
    public IPage<WorkFlowButton> getPageResult(QueryPage<WorkFlowButton> queryPage) {
        LambdaQueryWrapper<WorkFlowButton> queryWrapper = Wrappers.lambdaQuery();
        WorkFlowButton workFlowButton = queryPage.getCondition();
        if (workFlowButton != null) {
            if (StringUtils.isNotBlank(workFlowButton.getName())) {
                queryWrapper.like(WorkFlowButton::getName, workFlowButton.getName());
            }
            if (workFlowButton.getIsEnable() != null) {
                queryWrapper.eq(WorkFlowButton::getIsEnable, workFlowButton.getIsEnable());
            }
        }
        queryWrapper.orderByAsc(WorkFlowButton::getSort);
        return getBaseMapper().getPageResult(queryPage.getPage(), queryWrapper);
    }

    @Override
    public boolean updateButton(WorkFlowButton workFlowButton) {
        Preconditions.checkArgument(workFlowButton.getId() != null, 30002);
        WorkFlowButton button = this.getById(workFlowButton.getId());
        Preconditions.checkArgument(button != null, "获取按钮信息失败");

        if (!button.getName().equals(workFlowButton.getName())) {
            button = this.getOne(Wrappers.<WorkFlowButton>lambdaQuery().eq(WorkFlowButton::getName, workFlowButton.getName()));
            Preconditions.checkArgument(button == null, "按钮名称已存在");
        }

        return SqlHelper.retBool(getBaseMapper().updateById(workFlowButton));
    }

    @Override
    public WorkFlowButton getByCode(String code) {
        return this.getOne(Wrappers.<WorkFlowButton>lambdaQuery().eq(WorkFlowButton::getCode, code));
    }

    @Override
    public List<WorkFlowButton> getListByTaskId(String taskId) {
        Preconditions.checkArgument(StringUtils.isNotBlank(taskId), 30002);

        List<WorkFlowButton> buttons = new ArrayList<>();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        Preconditions.checkArgument(task != null, "获取任务信息失败");

        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        UserTask userTask = WorkFlowUtil.getUserTaskByKey(bpmnModel, task.getTaskDefinitionKey());
        if (userTask == null) {
            return buttons;
        }

        // 用户任务节点获取扩展内容
        List<ExtensionElement> buttonElements = WorkFlowUtil.getExtensionElements(userTask, EXTENSION_ELEMENT_BUTTON);
        if (CollectionUtils.isEmpty(buttonElements)) {
            return buttons;
        }

        buttonElements.forEach(element -> {
            String code = element.getAttributeValue(null, EXTENSION_ELEMENT_BUTTON_CODE);
            if (StringUtils.isNotBlank(code)) {
                WorkFlowButton workFlowButton = getByCode(code);
                if (workFlowButton != null) {
                    workFlowButton.setName(element.getAttributeValue(null, EXTENSION_ELEMENT_BUTTON_NAME));
                    buttons.add(workFlowButton);
                }
            }
        });

        return buttons;
    }

}
