package com.m2pool.common.security.auth;

import com.m2pool.common.core.exception.auth.NotLoginException;
import com.m2pool.common.core.exception.auth.NotPermissionException;
import com.m2pool.common.core.utils.SpringUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.security.annotation.Logical;
import com.m2pool.common.security.annotation.OpenApiPermissions;
import com.m2pool.common.security.annotation.RequiresPermissions;
import com.m2pool.common.security.service.OpenApiService;
import com.m2pool.common.security.utils.OpenApiUtils;
import com.m2pool.system.api.model.LoginUser;
import com.m2pool.system.api.model.OpenApiKeyInfo;
import org.springframework.util.PatternMatchUtils;

import javax.sound.midi.Soundbank;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * @Description 权限验证的逻辑实现类
 * @Date 2024/6/13 19:04
 * @Author dy
 */
public class OpenApiRequest {

    /** 所有权限标识 */
    private static final String ALL_PERMISSION = "*:*:*";

    private OpenApiService openApiService = SpringUtils.getBean(OpenApiService.class);

    /**
     * 会话注销
     */
    public void logout()
    {
        String apiKey = OpenApiUtils.getApiKey();
        if (apiKey == null)
        {
            return;
        }
        logoutByApiKey(apiKey);
    }

    /**
     * 会话注销，根据指定Token
     */
    public void logoutByApiKey(String apiKey)
    {
        openApiService.delOpenApiKey(apiKey);
    }

    /**
     * 检验用户是否已经生成过apiKey，如未生成，则抛出异常
     */
    public void checkApiKey(){getApiKey();}

    /**
     * 获取当前用户缓存信息, 如果未登录，则抛出异常
     *
     * @return 用户缓存信息
     */
    public OpenApiKeyInfo getApiKey()
    {
        String apiKey = OpenApiUtils.getApiKey();
        if (apiKey == null)
        {
            throw new NotLoginException("未提供API-KEY");
        }
        OpenApiKeyInfo apiKeyInfo = OpenApiUtils.getOpenApiKeyInfo();
        if (apiKeyInfo == null)
        {
                throw new NotLoginException("无效的API-KEY");
        }
        return apiKeyInfo;
    }

    /**
     * 获取当前用户缓存信息, 如果未登录，则抛出异常
     *
     * @param apiKey 前端传递的认证信息
     * @return 用户缓存信息
     */
    public OpenApiKeyInfo getOpenApiKeyInfo(String apiKey)
    {
        return openApiService.getOpenApiKeyInfo(apiKey);
    }

    /**
     * 验证当前api-key有效期, 如果相差不足120分钟，自动刷新缓存
     *
     * @param openApiKey 当前用户信息
     */
    public void verifyApiKeyExpire(OpenApiKeyInfo openApiKey)
    {
        openApiService.verifyApiKey(openApiKey);
    }

    /**
     * 根据注解(@RequiresPermissions)鉴权
     *
     * @param at 注解对象
     */
    public void checkByAnnotation(RequiresPermissions at)
    {
        String[] permissionArray = at.value();
        if (at.logical() == Logical.AND)
        {
            this.checkPermissionAnd(permissionArray);
        }
        else
        {
            this.checkPermissionOr(permissionArray);
        }
    }

    /**
     * 获取当前账号的权限列表
     *
     * @return 权限列表
     */
    public Set<String> getPermissionList()
    {
        try
        {
            OpenApiKeyInfo apiKeyInfo = getApiKey();
            return apiKeyInfo.getPermissions();
        }
        catch (Exception e)
        {
            return new HashSet<>();
        }
    }

    /**
     * 验证用户是否具备某权限
     *
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public boolean hasPermission(String permission)
    {
        System.out.println("hasPermission");
        return hasPermission(getPermissionList(), permission);
    }

    /**
     * 验证用户是否具备某权限, 如果验证未通过，则抛出异常: NotPermissionException
     *
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public void checkPermission(String permission)
    {
        System.out.println("OpenApiRequest.checkPermission");
        if (!hasPermission(getPermissionList(), permission))
        {
            throw new NotPermissionException(permission);
        }
    }

    /**
     * 根据注解(@RequiresPermissions)鉴权, 如果验证未通过，则抛出异常: NotPermissionException
     *
     * @param openApiPermissions 注解对象
     */
    public void checkPermission(OpenApiPermissions openApiPermissions)
    {
        if (openApiPermissions.logical() == Logical.AND)
        {
            checkPermissionAnd(openApiPermissions.value());
        }
        else
        {
            checkPermissionOr(openApiPermissions.value());
        }
    }

    /**
     * 验证用户是否含有指定权限，必须全部拥有
     *
     * @param permissions 权限列表
     */
    public void checkPermissionAnd(String... permissions)
    {
        Set<String> permissionList = getPermissionList();
        for (String permission : permissions)
        {
            if (!hasPermission(permissionList, permission))
            {
                throw new NotPermissionException(permission);
            }
        }
    }

    /**
     * 验证用户是否含有指定权限，只需包含其中一个
     *
     * @param permissions 权限码数组
     */
    public void checkPermissionOr(String... permissions)
    {
        System.out.println("OpenApiRequest.checkPermissionOr");
        Set<String> permissionList = getPermissionList();
        for (String permission : permissions)
        {
            if (hasPermission(permissionList, permission))
            {
                return;
            }
        }
        if (permissions.length > 0)
        {
            throw new NotPermissionException(permissions);
        }
    }


    /**
     * 判断是否包含权限
     *
     * @param authorities 权限列表
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public boolean hasPermission(Collection<String> authorities, String permission)
    {
        System.out.println("权限列表："+authorities);
        System.out.println("所需权限："+permission);
        return authorities.stream().filter(StringUtils::hasText)
                .anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(x, permission));
    }



}
