package tech.easyflow.ai.chattime.availability;

import org.springframework.stereotype.Component;
import tech.easyflow.ai.entity.BotDocumentCollection;
import tech.easyflow.ai.entity.DocumentCollection;
import tech.easyflow.ai.permission.KnowledgeReadAccessSnapshot;
import tech.easyflow.ai.permission.KnowledgeVisibilityQueryHelper;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.system.entity.vo.RoleCategoryAccessSnapshot;
import tech.easyflow.system.enums.CategoryResourceType;
import tech.easyflow.system.service.CategoryPermissionService;
import tech.easyflow.system.service.SysDeptService;

import java.math.BigInteger;
import java.util.Collections;
import java.util.Set;

/**
 * 知识库聊天时可用性判定器。
 */
@Component
public class ChatTimeKnowledgeAvailabilityResolver implements ChatTimeToolAvailabilityResolver {

    private final KnowledgeVisibilityQueryHelper knowledgeVisibilityQueryHelper;
    private final CategoryPermissionService categoryPermissionService;
    private final SysDeptService sysDeptService;

    public ChatTimeKnowledgeAvailabilityResolver(KnowledgeVisibilityQueryHelper knowledgeVisibilityQueryHelper,
                                                 CategoryPermissionService categoryPermissionService,
                                                 SysDeptService sysDeptService) {
        this.knowledgeVisibilityQueryHelper = knowledgeVisibilityQueryHelper;
        this.categoryPermissionService = categoryPermissionService;
        this.sysDeptService = sysDeptService;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean supports(Object candidate) {
        return candidate instanceof DocumentCollection || candidate instanceof BotDocumentCollection;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ChatTimeToolAvailabilityDecision resolve(ChatTimeToolAvailabilityContext context, Object candidate) {
        LoginAccount loginAccount = context == null ? null : context.getLoginAccount();
        if (loginAccount == null || loginAccount.getId() == null) {
            return ChatTimeToolAvailabilityDecision.unavailable("CHAT_TIME_LOGIN_ACCOUNT_MISSING", "聊天上下文缺少当前用户身份");
        }
        DocumentCollection knowledge = extractKnowledge(candidate);
        if (knowledge == null) {
            return ChatTimeToolAvailabilityDecision.unavailable("CHAT_TIME_KNOWLEDGE_MISSING", "聊天绑定的知识库不存在");
        }
        KnowledgeReadAccessSnapshot readSnapshot = buildReadSnapshot(loginAccount);
        if (knowledgeVisibilityQueryHelper.canRead(knowledge, readSnapshot)) {
            return ChatTimeToolAvailabilityDecision.available();
        }
        return ChatTimeToolAvailabilityDecision.unavailable("CHAT_TIME_KNOWLEDGE_FORBIDDEN", "当前用户无权在聊天中访问该知识库");
    }

    /**
     * 基于显式登录快照构造知识库读权限快照，避免依赖线程登录态。
     *
     * @param loginAccount 当前聊天用户
     * @return 读权限快照
     */
    protected KnowledgeReadAccessSnapshot buildReadSnapshot(LoginAccount loginAccount) {
        RoleCategoryAccessSnapshot categoryAccess = categoryPermissionService.getAccess(
                CategoryResourceType.KNOWLEDGE.getCode(),
                loginAccount
        );
        if (categoryAccess.isSuperAdmin()) {
            return new KnowledgeReadAccessSnapshot(categoryAccess, Collections.emptySet());
        }
        BigInteger deptId = loginAccount.getDeptId();
        Set<BigInteger> readableDeptIds = deptId == null
                ? Collections.emptySet()
                : sysDeptService.getSelfAndAncestorDeptIds(deptId);
        return new KnowledgeReadAccessSnapshot(categoryAccess, readableDeptIds);
    }

    /**
     * 从聊天工具候选项中提取知识库实体。
     *
     * @param candidate 候选项
     * @return 知识库实体
     */
    protected DocumentCollection extractKnowledge(Object candidate) {
        if (candidate instanceof DocumentCollection documentCollection) {
            return documentCollection;
        }
        if (candidate instanceof BotDocumentCollection botDocumentCollection) {
            return botDocumentCollection.getKnowledge();
        }
        return null;
    }
}
