package com.flowable.local.work.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.flowable.action.api.bot.BaseBotActionResult;
import com.flowable.action.api.bot.BotActionResult;
import com.flowable.action.api.bot.BotService;
import com.flowable.action.api.history.HistoricActionInstance;
import com.flowable.action.api.intents.Intent;
import com.flowable.action.api.repository.ActionDefinition;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class StartProcessBot implements BotService {
    protected static final Logger LOGGER = LoggerFactory.getLogger(StartProcessBot.class);
    public static final String BOT_KEY = "start-process-bot";
    public static final String BOT_NAME = "start process bot";
    public static final String BOT_DESCRIPTION = "This bot starts a process.";

    private final RuntimeService runtimeService;
    private final ObjectMapper objectMapper;
    private final HistoryService historyService;

    public StartProcessBot(RuntimeService runtimeService,
                           ObjectMapper objectMapper,
                           HistoryService historyService) {
        this.runtimeService = runtimeService;
        this.objectMapper = objectMapper;
        this.historyService = historyService;
    }

    @Override
    public String getKey() { return BOT_KEY; }

    @Override
    public String getName() { return BOT_NAME; }

    @Override
    public String getDescription() { return BOT_DESCRIPTION; }

    @Override
    public BotActionResult invokeBot(HistoricActionInstance actionInstance, ActionDefinition actionDefinition, Map<String, Object> payload) {
        LOGGER.info(getKey() + " starting...");
        String rootCaseId = actionInstance.getScopeId();
        if (rootCaseId == null) {
            throw new RuntimeException(getKey() + " cannot get Scope Id from action button");
        }
        String taskModelId = null;
        try {
            taskModelId = payload.get("taskModelId").toString();
        } catch (Exception e) {
        }
        if (taskModelId == null) {
            throw new RuntimeException(getKey() + " cannot get taskModelId from payload");
        }
        LOGGER.info(getKey() + " starting task instance with taskModelId " + taskModelId + "...");
        ProcessInstance processInstance = this.runtimeService.createProcessInstanceBuilder()
                .processDefinitionKey(taskModelId)
                .tenantId(actionInstance.getTenantId())
                .variables(payload)
                .start();
        if (processInstance == null) {
            throw new RuntimeException(getKey() + " cannot find enabled task instance with taskModelId " + taskModelId);
        }
        LOGGER.info(getKey() + " task instance with taskModelId " + taskModelId + " successfully started");

        Map<String, Object> processVariables = processInstance.getProcessVariables();
        ObjectNode responsePayload = this.objectMapper.convertValue(processVariables, ObjectNode.class);
        responsePayload.put("id", processInstance.getId());
        return new BaseBotActionResult(responsePayload, Intent.NOOP);
    }
}
