package tech.easyflow.agent.security;

import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.stereotype.Component;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.common.satoken.util.SaTokenUtil;
import tech.easyflow.system.entity.vo.RoleCategoryAccessSnapshot;
import tech.easyflow.system.enums.CategoryResourceType;
import tech.easyflow.system.enums.VisibilityScope;
import tech.easyflow.system.service.CategoryPermissionService;
import tech.easyflow.system.service.SysDeptService;

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

import static tech.easyflow.agent.entity.table.AgentTableDef.AGENT;

/**
 * 将 Agent 的租户、分类、归属人与可见范围转换为数据库查询条件。
 */
@Component
public class AgentVisibilityQueryHelper {

    private final CategoryPermissionService categoryPermissionService;
    private final SysDeptService sysDeptService;

    /**
     * 创建 Agent 可见性查询助手。
     *
     * @param categoryPermissionService 分类权限服务
     * @param sysDeptService 部门服务
     */
    public AgentVisibilityQueryHelper(CategoryPermissionService categoryPermissionService,
                                      SysDeptService sysDeptService) {
        this.categoryPermissionService = categoryPermissionService;
        this.sysDeptService = sysDeptService;
    }

    /**
     * 将当前账号可读 Agent 范围追加到查询条件。
     *
     * @param queryWrapper Agent 查询条件
     */
    public void applyReadableAccess(QueryWrapper queryWrapper) {
        LoginAccount account = SaTokenUtil.getLoginAccount();
        BigInteger accountId = account == null ? null : account.getId();
        BigInteger tenantId = account == null ? null : account.getTenantId();
        if (accountId == null || tenantId == null) {
            queryWrapper.and(AGENT.ID.eq(BigInteger.valueOf(-1)));
            return;
        }
        // 项目没有启用全局租户过滤器，超级管理员也必须限制在当前租户。
        queryWrapper.and(AGENT.TENANT_ID.eq(tenantId));
        RoleCategoryAccessSnapshot access =
                categoryPermissionService.getCurrentAccess(CategoryResourceType.AGENT.getCode());
        if (access.isSuperAdmin()) {
            return;
        }
        QueryCondition owner = AGENT.CREATED_BY.eq(accountId);
        Set<BigInteger> readableDeptIds = account.getDeptId() == null
                ? Collections.emptySet()
                : sysDeptService.getSelfAndAncestorDeptIds(account.getDeptId());
        QueryCondition visible = buildScopeVisibleCondition(readableDeptIds);
        if (access.isRestricted()) {
            // Agent 未设置分类时表示不受分类白名单限制，仍需满足其可见范围。
            QueryCondition readableCategories = AGENT.CATEGORY_ID.isNull()
                    .and(buildScopeVisibleCondition(readableDeptIds));
            if (!access.getCategoryIds().isEmpty()) {
                readableCategories = readableCategories.or(
                        AGENT.CATEGORY_ID.in(access.getCategoryIds())
                                .and(buildScopeVisibleCondition(readableDeptIds)));
            }
            visible = readableCategories;
        }
        queryWrapper.and(owner.or(visible));
    }

    /**
     * 构建可见范围条件。
     *
     * @param readableDeptIds 当前账号可读取的部门 ID 集合
     * @return 可见范围条件
     */
    private QueryCondition buildScopeVisibleCondition(Set<BigInteger> readableDeptIds) {
        QueryCondition scopeVisible = AGENT.VISIBILITY_SCOPE.eq(VisibilityScope.PUBLIC.name());
        if (!readableDeptIds.isEmpty()) {
            scopeVisible = scopeVisible.or(AGENT.VISIBILITY_SCOPE.eq(VisibilityScope.DEPT.name())
                    .and(AGENT.DEPT_ID.in(readableDeptIds)));
        }
        return scopeVisible;
    }
}
