package tech.easyflow.ai.service.impl;

import tech.easyflow.ai.entity.BotWorkflow;
import tech.easyflow.ai.mapper.BotWorkflowMapper;
import tech.easyflow.ai.service.BotWorkflowService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.easyflow.common.cache.RedisLockExecutor;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.time.Duration;
import com.mybatisflex.core.query.QueryWrapper;

/**
 *  服务层实现。
 *
 * @author michael
 * @since 2024-08-28
 */
@Service
public class BotWorkflowServiceImpl extends ServiceImpl<BotWorkflowMapper, BotWorkflow> implements BotWorkflowService {

    private static final String BOT_BINDING_LOCK_KEY_PREFIX = "easyflow:lock:bot:binding:";
    private static final Duration LOCK_WAIT_TIMEOUT = Duration.ofSeconds(2);
    private static final Duration LOCK_LEASE_TIMEOUT = Duration.ofSeconds(10);

    @Resource
    private RedisLockExecutor redisLockExecutor;

    @Override
    public List<BotWorkflow> listByBotId(BigInteger botId) {

        QueryWrapper queryWrapper = QueryWrapper.create();
        queryWrapper.eq(BotWorkflow::getBotId,botId);

        return list(queryWrapper);
    }

    @Override
    @Transactional
    public void saveBotAndWorkflowTool(BigInteger botId, BigInteger[] workflowIds) {
        redisLockExecutor.executeWithLock(BOT_BINDING_LOCK_KEY_PREFIX + botId, LOCK_WAIT_TIMEOUT, LOCK_LEASE_TIMEOUT, () -> {
            this.remove(QueryWrapper.create().eq(BotWorkflow::getBotId, botId));

            Set<BigInteger> uniqueWorkflowIds = new LinkedHashSet<>();
            if (workflowIds != null) {
                for (BigInteger workflowId : workflowIds) {
                    if (workflowId != null) {
                        uniqueWorkflowIds.add(workflowId);
                    }
                }
            }
            if (uniqueWorkflowIds.isEmpty()) {
                return;
            }

            List<BotWorkflow> list = new ArrayList<>(uniqueWorkflowIds.size());
            for (BigInteger workflowId : uniqueWorkflowIds) {
                BotWorkflow botWorkflow = new BotWorkflow();
                botWorkflow.setBotId(botId);
                botWorkflow.setWorkflowId(workflowId);
                list.add(botWorkflow);
            }
            this.saveBatch(list);
        });
    }
}
