package tech.easyflow.skill.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.skill.entity.Skill;
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.skill.entity.table.SkillTableDef.SKILL;

/**
 * 将 Skill 的分类、归属人与可见范围权限转换为数据库可执行的读取条件。
 */
@Component
public class SkillVisibilityQueryHelper {

    private final CategoryPermissionService categoryPermissionService;
    private final SysDeptService sysDeptService;

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

    /**
     * 将当前登录用户的 Skill 读取权限追加到查询条件。
     *
     * @param queryWrapper 查询条件
     */
    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(SKILL.ID.eq(BigInteger.valueOf(-1)));
            return;
        }
        // 超级管理员也只能读取当前租户；项目未启用 MyBatis-Flex 全局租户过滤器。
        queryWrapper.and(SKILL.TENANT_ID.eq(tenantId));
        RoleCategoryAccessSnapshot access = categoryPermissionService.getCurrentAccess(CategoryResourceType.SKILL.getCode());
        if (access.isSuperAdmin()) {
            return;
        }
        QueryCondition owner = SKILL.CREATED_BY.eq(accountId);
        if (access.isRestricted() && access.getCategoryIds().isEmpty()) {
            queryWrapper.and(owner);
            return;
        }
        Set<BigInteger> readableDeptIds = account.getDeptId() == null
                ? Collections.emptySet() : sysDeptService.getSelfAndAncestorDeptIds(account.getDeptId());
        QueryCondition visible = SKILL.VISIBILITY_SCOPE.eq(VisibilityScope.PUBLIC.name());
        if (!readableDeptIds.isEmpty()) {
            visible = visible.or(SKILL.VISIBILITY_SCOPE.eq(VisibilityScope.DEPT.name())
                    .and(SKILL.DEPT_ID.in(readableDeptIds)));
        }
        if (access.isRestricted()) {
            visible = SKILL.CATEGORY_ID.in(access.getCategoryIds()).and(visible);
        }
        queryWrapper.and(owner.or(visible));
    }
}
