package tech.easyflow.agent.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.agent.entity.Agent;
import tech.easyflow.agent.entity.AgentKnowledgeBinding;
import tech.easyflow.agent.mapper.AgentKnowledgeBindingMapper;
import tech.easyflow.agent.mapper.AgentMapper;
import tech.easyflow.agent.service.AgentKnowledgeBindingService;
import tech.easyflow.ai.entity.DocumentCollection;
import tech.easyflow.ai.enums.PublishStatus;
import tech.easyflow.ai.rag.KnowledgeRetrievalModes;
import tech.easyflow.ai.service.DocumentCollectionService;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.common.satoken.util.SaTokenUtil;
import tech.easyflow.common.web.exceptions.BusinessException;
import tech.easyflow.system.enums.CategoryResourceType;
import tech.easyflow.system.enums.ResourceAction;
import tech.easyflow.system.service.ResourceAccessService;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * Agent 知识库绑定服务实现。
 */
@Service
public class AgentKnowledgeBindingServiceImpl extends ServiceImpl<AgentKnowledgeBindingMapper, AgentKnowledgeBinding>
        implements AgentKnowledgeBindingService {

    private static final String DEFAULT_RETRIEVAL_MODE = "HYBRID";

    @Resource
    private AgentMapper agentMapper;
    @Resource
    private DocumentCollectionService documentCollectionService;
    @Resource
    private ResourceAccessService resourceAccessService;

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AgentKnowledgeBinding> replaceBindings(BigInteger agentId, List<AgentKnowledgeBinding> bindings) {
        Agent agent = requireAgent(agentId);
        resourceAccessService.assertAccess(CategoryResourceType.AGENT, agent, ResourceAction.MANAGE, "无权限管理该 Agent");
        remove(QueryWrapper.create().where("agent_id = ?", agentId));
        if (bindings == null || bindings.isEmpty()) {
            return Collections.emptyList();
        }
        for (int i = 0; i < bindings.size(); i++) {
            AgentKnowledgeBinding binding = bindings.get(i);
            validateBinding(binding);
            applyBindingDefaults(agent, binding, i);
        }
        saveBatch(bindings);
        return listEnabled(agentId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<AgentKnowledgeBinding> listEnabled(BigInteger agentId) {
        return list(QueryWrapper.create()
                .where("agent_id = ?", agentId)
                .and("enabled = ?", true)
                .orderBy("sort_no asc, id asc"));
    }

    private Agent requireAgent(BigInteger agentId) {
        Agent agent = agentMapper.selectOneById(agentId);
        if (agent == null) {
            throw new BusinessException("Agent 不存在");
        }
        return agent;
    }

    private void validateBinding(AgentKnowledgeBinding binding) {
        if (binding == null || binding.getKnowledgeId() == null) {
            throw new BusinessException("知识库绑定参数不完整");
        }
        DocumentCollection knowledge = documentCollectionService.getById(binding.getKnowledgeId());
        if (knowledge == null || PublishStatus.from(knowledge.getPublishStatus()) != PublishStatus.PUBLISHED) {
            throw new BusinessException("绑定知识库不存在或未发布");
        }
        KnowledgeRetrievalModes.parse(binding.getRetrievalMode());
        resourceAccessService.assertAccess(CategoryResourceType.KNOWLEDGE, knowledge, ResourceAction.USE, "无权限绑定该知识库");
    }

    private void applyBindingDefaults(Agent agent, AgentKnowledgeBinding binding, int index) {
        LoginAccount account = requireCurrentLoginAccount();
        Date now = new Date();
        binding.setId(null);
        binding.setTenantId(agent.getTenantId());
        binding.setAgentId(agent.getId());
        if (binding.getRetrievalMode() == null || binding.getRetrievalMode().isBlank()) {
            binding.setRetrievalMode(DEFAULT_RETRIEVAL_MODE);
        } else {
            binding.setRetrievalMode(binding.getRetrievalMode().trim().toUpperCase());
        }
        binding.setEnabled(binding.getEnabled() == null || binding.getEnabled());
        binding.setSortNo(binding.getSortNo() == null ? index : binding.getSortNo());
        binding.setCreated(now);
        binding.setCreatedBy(account.getId());
        binding.setModified(now);
        binding.setModifiedBy(account.getId());
    }

    private LoginAccount requireCurrentLoginAccount() {
        try {
            return SaTokenUtil.getLoginAccount();
        } catch (Exception e) {
            throw new BusinessException("当前登录状态失效，请重新登录后再试");
        }
    }
}
