package tech.easyflow.ai.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.easyflow.ai.enums.KnowledgeShareActionScope;
import tech.easyflow.ai.service.KnowledgeSharePermissionService;
import tech.easyflow.common.web.exceptions.BusinessException;
import tech.easyflow.system.entity.SysApiKey;
import tech.easyflow.system.entity.SysApiKeyResource;
import tech.easyflow.system.entity.SysApiKeyResourceMapping;
import tech.easyflow.system.service.SysApiKeyResourceMappingService;
import tech.easyflow.system.service.SysApiKeyResourceService;
import tech.easyflow.system.service.SysApiKeyService;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 知识库分享权限服务实现。
 */
@Service
public class KnowledgeSharePermissionServiceImpl implements KnowledgeSharePermissionService {

    public static final String RESOURCE_TYPE_KNOWLEDGE = "KNOWLEDGE";

    private static final Map<String, List<String>> URI_SCOPE_MAPPING = new LinkedHashMap<>();

    static {
        URI_SCOPE_MAPPING.put(KnowledgeShareActionScope.VIEW.name(), List.of(
            "/public-api/knowledge-share/detail",
            "/public-api/knowledge-share/document/page",
            "/public-api/knowledge-share/document/download",
            "/public-api/knowledge-share/document/import/task/detail",
            "/public-api/knowledge-share/documentChunk/page",
            "/public-api/knowledge-share/faq/page",
            "/public-api/knowledge-share/faq/detail"
        ));
        URI_SCOPE_MAPPING.put(KnowledgeShareActionScope.SEARCH.name(), List.of(
            "/public-api/knowledge-share/search"
        ));
        URI_SCOPE_MAPPING.put(KnowledgeShareActionScope.CONTENT_CREATE.name(), List.of(
            "/public-api/knowledge-share/document/import/analyze",
            "/public-api/knowledge-share/document/import/preview",
            "/public-api/knowledge-share/document/import/commit",
            "/public-api/knowledge-share/document/import/task/create",
            "/public-api/knowledge-share/document/import/task/preview",
            "/public-api/knowledge-share/document/import/task/startIndex",
            "/public-api/knowledge-share/document/import/task/retryParse",
            "/public-api/knowledge-share/document/import/task/retryIndex",
            "/public-api/knowledge-share/faq/save"
        ));
        URI_SCOPE_MAPPING.put(KnowledgeShareActionScope.CONTENT_UPDATE.name(), List.of(
            "/public-api/knowledge-share/documentChunk/update",
            "/public-api/knowledge-share/faq/update"
        ));
        URI_SCOPE_MAPPING.put(KnowledgeShareActionScope.CONTENT_DELETE.name(), List.of(
            "/public-api/knowledge-share/document/remove",
            "/public-api/knowledge-share/documentChunk/remove",
            "/public-api/knowledge-share/faq/remove"
        ));
        URI_SCOPE_MAPPING.put(KnowledgeShareActionScope.IMPORT_EXPORT.name(), List.of(
            "/public-api/knowledge-share/faq/importExcel",
            "/public-api/knowledge-share/faq/exportExcel",
            "/public-api/knowledge-share/faq/downloadImportTemplate"
        ));
    }

    @Resource
    private SysApiKeyService sysApiKeyService;
    @Resource
    private SysApiKeyResourceService resourceService;
    @Resource
    private SysApiKeyResourceMappingService mappingService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void grantApiShare(BigInteger apiKeyId, BigInteger knowledgeId, Set<String> actionScopes) {
        if (apiKeyId == null) {
            throw new BusinessException("系统访问令牌不能为空");
        }
        if (knowledgeId == null) {
            throw new BusinessException("知识库不能为空");
        }
        SysApiKey apiKey = sysApiKeyService.getById(apiKeyId);
        if (apiKey == null) {
            throw new BusinessException("系统访问令牌不存在");
        }
        Set<String> normalizedScopes = KnowledgeShareActionScope.normalize(actionScopes);
        if (normalizedScopes.isEmpty()) {
            throw new BusinessException("动作范围不能为空");
        }

        mappingService.removeScopedMappings(apiKeyId, RESOURCE_TYPE_KNOWLEDGE, knowledgeId);
        List<SysApiKeyResourceMapping> rows = new ArrayList<>();
        for (String scope : normalizedScopes) {
            List<String> uris = URI_SCOPE_MAPPING.get(scope);
            if (uris == null || uris.isEmpty()) {
                continue;
            }
            for (String uri : uris) {
                SysApiKeyResource resource = ensureResource(uri);
                SysApiKeyResourceMapping row = new SysApiKeyResourceMapping();
                row.setApiKeyId(apiKeyId);
                row.setApiKeyResourceId(resource.getId());
                row.setResourceType(RESOURCE_TYPE_KNOWLEDGE);
                row.setResourceTargetId(knowledgeId);
                row.setActionScope(scope);
                rows.add(row);
            }
        }
        if (!rows.isEmpty()) {
            mappingService.saveBatch(rows);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void replaceApiShareEnabled(BigInteger apiKeyId, boolean enabled) {
        if (apiKeyId == null) {
            throw new BusinessException("系统访问令牌不能为空");
        }
        SysApiKey apiKey = sysApiKeyService.getById(apiKeyId);
        if (apiKey == null) {
            throw new BusinessException("系统访问令牌不存在");
        }
        mappingService.removeScopedMappings(apiKeyId, RESOURCE_TYPE_KNOWLEDGE);
        if (!enabled) {
            return;
        }

        List<SysApiKeyResourceMapping> rows = new ArrayList<>();
        for (String scope : KnowledgeShareActionScope.defaultApiScopes()) {
            List<String> uris = URI_SCOPE_MAPPING.get(scope);
            if (uris == null || uris.isEmpty()) {
                continue;
            }
            for (String uri : uris) {
                SysApiKeyResource resource = ensureResource(uri);
                SysApiKeyResourceMapping row = new SysApiKeyResourceMapping();
                row.setApiKeyId(apiKeyId);
                row.setApiKeyResourceId(resource.getId());
                row.setResourceType(RESOURCE_TYPE_KNOWLEDGE);
                row.setActionScope(scope);
                rows.add(row);
            }
        }
        if (!rows.isEmpty()) {
            mappingService.saveBatch(rows);
        }
    }

    @Override
    public void assertApiShare(BigInteger apiKeyId, String requestUri, BigInteger knowledgeId, String actionScope) {
        if (apiKeyId == null || knowledgeId == null) {
            throw new BusinessException("API 分享鉴权参数不完整");
        }
        sysApiKeyService.checkResourceScope(apiKeyId, requestUri, RESOURCE_TYPE_KNOWLEDGE, knowledgeId, actionScope);
    }

    private SysApiKeyResource ensureResource(String requestInterface) {
        QueryWrapper wrapper = QueryWrapper.create()
            .eq(SysApiKeyResource::getRequestInterface, requestInterface);
        SysApiKeyResource resource = resourceService.getOne(wrapper);
        if (resource != null) {
            return resource;
        }
        resource = new SysApiKeyResource();
        resource.setRequestInterface(requestInterface);
        resource.setTitle("知识库分享接口");
        resourceService.save(resource);
        return resource;
    }
}
