package cn.axzo.msg.center.message.controller;

import cn.axzo.msg.center.dal.MessageTemplateButtonV3Dao;
import cn.axzo.msg.center.dal.MessageTemplateV3Dao;
import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3;
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.RouterButtonSourceEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.service.pending.client.WorkflowButtonSyncClient;
import cn.axzo.msg.center.service.pending.request.WorkflowSyncButtonsRequest;
import cn.axzo.msg.center.service.pending.request.WorkflowSyncButtonsRequest.WorkflowButton;
import cn.axzo.msg.center.utils.AsyncRunTasks;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;

/**
 * @author yanglin
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class WorkflowButtonSyncClientController implements WorkflowButtonSyncClient {

    private final MessageTemplateV3Dao messageTemplateV3Dao;
    private final MessageTemplateButtonV3Dao messageTemplateButtonV3Dao;

    @Override
    public CommonResponse<Void> syncButtons(WorkflowSyncButtonsRequest request) throws Exception {
        Map<String, MessageTemplateV3> code2Template = messageTemplateV3Dao.lambdaQuery()
                .list().stream()
                .collect(toMap(MessageTemplateV3::getCode, identity()));
        Map<String, WorkflowButton> code2FlowButton =
                request.getButtons().stream()
                        .collect(toMap(WorkflowButton::getCode, identity(),
                                (oldValue, newValue) -> oldValue));
        Map<String, WorkflowButton> name2FlowButton =
                request.getButtons().stream()
                        .collect(toMap(WorkflowButton::getName, identity(),
                                (oldValue, newValue) -> oldValue));
        List<MessageTemplateButtonV3> buttons =
                messageTemplateButtonV3Dao.lambdaQuery().list();

        log.info("start sync buttons, buttons={}", buttons.size());
        int nThreads = 10;
        AsyncRunTasks tasks = new AsyncRunTasks(Executors.newFixedThreadPool(nThreads));
        Semaphore semaphore = new Semaphore(nThreads);
        for (MessageTemplateButtonV3 button : buttons) {
            semaphore.acquire();
            tasks.runAsync(() -> {
                try {
                    sync(code2Template, code2FlowButton, name2FlowButton, button);
                } catch (Exception e) {
                    log.warn("sync button error, button={}", button, e);
                } finally {
                    semaphore.release();
                }
            });
        }
        tasks.awaitTermination();
        log.info("finish sync buttons, buttons={}", buttons.size());
        return CommonResponse.success();
    }

    private void sync(Map<String, MessageTemplateV3> code2Template,
                      Map<String, WorkflowButton> code2FlowButton,
                      Map<String, WorkflowButton> name2FlowButton,
                      MessageTemplateButtonV3 button) {
        if (button.getSource() != RouterButtonSourceEnum.SYSTEM)
            return;
        MessageTemplateV3 template = code2Template.get(button.getTemplateCode());
        if (template.getMsgCategory() != MessageCategoryEnum.APPROVAL_PENDING_MESSAGE)
            return;

        MessageTemplateButtonV3 update = new MessageTemplateButtonV3();
        WorkflowButton workflowButton = code2FlowButton.get(button.getCode());
        if (workflowButton == null) {
            workflowButton = name2FlowButton.get(button.getName());
            if (workflowButton != null)
                update.setCode(workflowButton.getCode());
        }
        if (workflowButton == null) return;
        update.setId(button.getId());
        update.setCategory(workflowButton.getCategory());
        if (button.getCategory() == RouterCategoryEnum.JUMP) {
            UrlConfig urlConfig = new UrlConfig();
            urlConfig.setDefaultUrl(workflowButton.getUrl());
            update.setUrlConfig(urlConfig);
            update.setApiUrl("");
        } else {
            String apiUrl = workflowButton.getUrl();
            if (apiUrl == null) apiUrl = "";
            update.setApiUrl(apiUrl);
        }
        messageTemplateButtonV3Dao.updateById(update);
    }

}