#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import re

from django.contrib.auth.models import AnonymousUser
from django.core.cache import cache
from django.db.models import F
from rest_framework.permissions import BasePermission

from django_base_ai.system.models import ApiWhiteList


def validation_api(req_api, valid_api):
    """
    验证当前用户是否有接口权限
    :param req_api: 当前请求的接口
    :param valid_api: 用于验证的接口
    :return: True或者False
    """
    if valid_api is not None:
        valid_api_pattern = valid_api.replace("{id}", ".*?")
        match_obj = re.match(valid_api_pattern, req_api, re.M | re.I)
        if match_obj:
            return True
        else:
            return False
    else:
        return False


class AnonymousUserPermission(BasePermission):
    """
    匿名用户权限
    """

    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        return True


def re_uuid(api):
    """
    将接口的uuid替换掉
    :param api:
    :return:
    """
    pattern = re.compile(r"[a-f\d]{4}(?:[a-f\d]{4}-){4}[a-f\d]{12}/$")
    m = pattern.search(api)
    if m:
        res = api.replace(m.group(0), ".*/")
        return res
    else:
        return None


class CustomPermission(BasePermission):
    """自定义权限"""

    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        # 判断是否是超级管理员
        if request.user.is_superuser:
            return True
        else:
            api = request.path  # 当前请求接口
            method = request.method  # 当前请求方法
            method_list = ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"]
            method = method_list.index(method)
            # ***接口白名单***
            api_white_list = ApiWhiteList.objects.values(permission__api=F("url"), permission__method=F("method"))
            api_white_list = [
                str(item.get("permission__api").replace("{id}", "([a-zA-Z0-9-]+)"))
                + ":"
                + str(item.get("permission__method"))
                + "$"
                for item in api_white_list
                if item.get("permission__api")
            ]
            # ********#
            if not hasattr(request.user, "role"):
                return False
            user_api_list = request.user.role.values(
                "permission__api", "permission__method"
            )  # 获取当前用户的角色拥有的所有接口
            api_list = [
                str(item.get("permission__api").replace("{id}", "([a-zA-Z0-9-]+)"))
                + ":"
                + str(item.get("permission__method"))
                + "$"
                for item in user_api_list
                if item.get("permission__api")
            ]
            new_api_ist = api_white_list + api_list
            new_api = api + ":" + str(method)
            for item in new_api_ist:
                match_obj = re.match(item, new_api, re.M | re.I)
                if match_obj is None:
                    continue
                else:
                    return True
            else:
                return False


class OpenApiPermission(BasePermission):
    def has_permission(self, request, view):
        access_token = request.META.get("HTTP_AUTHORIZATION", None)
        if access_token is None:
            access_token = request.data.get("access_token", None)
        return access_token and access_token in cache


class SuperuserPermission(BasePermission):
    """
    超级管理员权限类
    """

    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        # 判断是否是超级管理员
        if request.user.is_superuser:
            return True


class AdminPermission(BasePermission):
    """
    普通管理员权限类
    """

    def has_permission(self, request, view):
        if isinstance(request.user, AnonymousUser):
            return False
        # 判断是否是超级管理员
        is_superuser = request.user.is_superuser
        # 判断是否是管理员角色
        is_admin = request.user.role.values_list("admin", flat=True)
        if is_superuser or True in is_admin:
            return True
