package tech.easyflow.ai.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.easyflow.ai.entity.BotPlugin;
import tech.easyflow.ai.entity.Plugin;
import tech.easyflow.ai.mapper.BotPluginMapper;
import tech.easyflow.ai.mapper.PluginMapper;
import tech.easyflow.ai.service.BotPluginService;
import tech.easyflow.common.cache.RedisLockExecutor;

import javax.annotation.Resource;
import java.time.Duration;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import static tech.easyflow.ai.entity.table.BotPluginTableDef.BOT_PLUGIN;

/**
 *  服务层实现。
 *
 * @author michael
 * @since 2025-04-07
 */
@Service
public class BotPluginServiceImpl extends ServiceImpl<BotPluginMapper, BotPlugin> implements BotPluginService {

    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 BotPluginMapper botPluginMapper;

    @Resource
    private PluginMapper pluginMapper;

    @Resource
    private RedisLockExecutor redisLockExecutor;

    @Override
    public List<Plugin> getList(String botId) {
        QueryWrapper w = QueryWrapper.create();
        w.select(BOT_PLUGIN.PLUGIN_ITEM_ID)
                .where(BOT_PLUGIN.BOT_ID.eq(botId));
        List<BigInteger> pluginIds = botPluginMapper.selectListByQueryAs(w, BigInteger.class);
        return pluginMapper.selectListByIds(pluginIds);
    }

    @Override
    public boolean doRemove(String botId, String pluginToolId) {
        QueryWrapper w = QueryWrapper.create();
        w.select(BOT_PLUGIN.ID)
                .where(BOT_PLUGIN.BOT_ID.eq(botId))
                .and(BOT_PLUGIN.PLUGIN_ITEM_ID.eq(pluginToolId));
        BigInteger id = botPluginMapper.selectOneByQueryAs(w, BigInteger.class);
        int delete = botPluginMapper.deleteById(id);
        return delete > 0;
    }

    @Override
    public List<BigInteger> getBotPluginToolIds(String botId) {
        QueryWrapper queryWrapper = QueryWrapper.create().select(BOT_PLUGIN.PLUGIN_ITEM_ID).where(BOT_PLUGIN.BOT_ID.eq(botId));
        return botPluginMapper.selectListByQueryAs(queryWrapper, BigInteger.class);
    }

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

            Set<BigInteger> uniquePluginToolIds = new LinkedHashSet<>();
            if (pluginToolIds != null) {
                for (BigInteger pluginToolId : pluginToolIds) {
                    if (pluginToolId != null) {
                        uniquePluginToolIds.add(pluginToolId);
                    }
                }
            }
            if (uniquePluginToolIds.isEmpty()) {
                return;
            }

            List<BotPlugin> list = new ArrayList<>(uniquePluginToolIds.size());
            for (BigInteger pluginToolId : uniquePluginToolIds) {
                BotPlugin aiBotPluginTool = new BotPlugin();
                aiBotPluginTool.setBotId(botId);
                aiBotPluginTool.setPluginItemId(pluginToolId);
                list.add(aiBotPluginTool);
            }
            this.saveBatch(list);
        });
    }
}
