from django.db import models
from django.conf import settings
# Create your models here.
from django.utils.translation import gettext_lazy as _
import django.utils.timezone as timezone



# 菜单表
class Menu(models.Model):    
    #slug = models.SlugField( _(_('Slug')  )   
    title = models.CharField(max_length=50, verbose_name=_('菜单名'))
    # 菜单显示图标
    icon = models.CharField(
        max_length=32,
        verbose_name=_('菜单图标'),
        null=True,
        blank=True
    )
    # 指定属于哪个父级菜单
    parent = models.ForeignKey(
        'self',
        verbose_name=_('父级菜单'),
        null=True,
        blank=True,
        help_text=_('如果添加的是子菜单，请选择父菜单'),
        on_delete=models.CASCADE
    )

    priority = models.IntegerField(
        verbose_name=_('顺序序号'),
        null=True,
        blank=True,
        default=10000,
        help_text=_('菜单的显示顺序，优先级越小显示越靠前')
    )
    level=models.SmallIntegerField(_('层级'),default=1,blank=True,null=True)
    url = models.CharField(_('URL地址'),max_length=100, blank=True, null=True)    
    content_type_id=models.IntegerField(_('django_content_type'),blank=True,null=True)
    companys_only=models.JSONField(_('限定企业'),default=list,blank=True,null=True)   
    remark=models.CharField(_('备注说明'),max_length=50,blank=True,null=True)        

    def __str__(self):
        return "{parent}{title}".format(title=self.title, parent="%s-->" % self.parent.title if self.parent else '')


    def save(self, *args, **kwargs):
        if self.parent:
            self.level=self.parent.level+1       
        super(Menu, self).save(*args, **kwargs) 

    class Meta:
        verbose_name = _('菜单表')
        verbose_name_plural = _('菜单表')
        ordering = ["priority","id"]  # 根据优先级和id来排序


#2021-09-08 企业菜单表
class CompanyMenu(models.Model):
    company=models.ForeignKey('company.Company',verbose_name=_('所属企业'),on_delete=models.CASCADE)        
    title = models.CharField(max_length=50, verbose_name=_('菜单名'))
    # 菜单显示图标
    icon = models.CharField(
        max_length=32,
        verbose_name=_('菜单图标'),
        null=True,
        blank=True
    )
    # 指定属于哪个父级菜单
    parent = models.ForeignKey(
        'self',
        verbose_name=_('父级菜单'),
        null=True,
        blank=True,
        help_text=_('如果添加的是子菜单，请选择父菜单'),
        on_delete=models.CASCADE
    )

    priority = models.IntegerField(
        verbose_name=_('顺序序号'),
        null=True,
        blank=True,
        default=10000,
        help_text=_('菜单的显示顺序，优先级越小显示越靠前')
    )
    level=models.SmallIntegerField(_('层级'),default=1,blank=True,null=True)
    url = models.CharField(_('URL地址'),max_length=100, blank=True, null=True)     
    remark=models.CharField(_('备注说明'),max_length=50,blank=True,null=True)   
    id0=models.IntegerField(_('原系统菜单ID'),blank=True,null=True)
    parent_id0=models.IntegerField(_('原系统菜单父级ID'),blank=True,null=True)
    content_type_id=models.IntegerField(_('django_content_type'),blank=True,null=True)

    def __str__(self):
        return "{parent}{title}".format(title=self.title, parent="%s-->" % self.parent.title if self.parent else '')


    def save(self, *args, **kwargs):
        if self.parent:
            self.level=self.parent.level+1       
        super(CompanyMenu, self).save(*args, **kwargs) 

    class Meta:
        verbose_name = _('企业菜单表')
        verbose_name_plural = _('企业菜单表')
        ordering = ["priority","id"]  # 根据优先级和id来排序








class CGroupMenu(models.Model):
    company=models.ForeignKey('company.Company',verbose_name='所属企业',blank=True,null=True,on_delete=models.CASCADE)
    cgroup=models.OneToOneField('company.CGroup',verbose_name=_('企业功能组别'),on_delete=models.CASCADE)
    menus=models.JSONField(_('企业操作菜单'),default=list,blank=True,null=True)
    tm_add = models.DateTimeField('创建时间',default = timezone.now)
    tm_edit = models.DateTimeField('最后修改时间', auto_now = True)
    
    class Meta:
        verbose_name = _('企业功能组别菜单')
        verbose_name_plural = _('企业功能组别菜单')



class DictCache(object):
    """A simple in-memory dict cache

    :param timeout: Number of seconds until an item in the cache expires.
    """

    def __init__(self, timeout=60):
        self.timeout = timeout
        self.data = {}

    @property
    def disabled(self):
        return self.timeout == 0

    def get(self, key, default=None):
        now = time.time()
        value, expires = self.data.get(key, (default, now))
        if now > expires:
            self.data.pop(key)
            return default
        return value

    def set(self, key, value):
        self.data[key] = (value, time.time() + self.timeout)

    def clear(self):
        self.data.clear()




class PrvCat(models.Model):
    name=models.CharField(_('大类名称'),max_length=30,unique=True)
    sn=models.SmallIntegerField(_('序号'),default=0,blank=True,null=True)
    remark=models.CharField(_('备注说明'),max_length=50,blank=True,null=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _('权限大类')
        verbose_name_plural = _('权限大类')
        ordering=['sn','name']

    
class PrvSub(models.Model):
    cat=models.ForeignKey(PrvCat,verbose_name=_('权限大类'),on_delete=models.CASCADE)
    name=models.CharField(_('子类名称'),max_length=30)
    sn=models.SmallIntegerField(_('序号'),default=0,blank=True,null=True)
    remark=models.CharField(_('权限子类'),max_length=50,blank=True,null=True)
    
    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _('权限子类')
        verbose_name_plural = _('权限子类')
        unique_together = ('cat', 'name')
        ordering=['cat','sn','name']


class PrvAction(models.Model):
    name=models.CharField(_('操作名称'),max_length=20,unique=True)
    remark=models.CharField(_('备注说明'),max_length=50,blank=True,null=True)

    class Meta:
        verbose_name = _('权限操作')
        verbose_name_plural = _('权限操作')




class Privilege(models.Model):   
    cat=models.ForeignKey(PrvCat,verbose_name=_('大类'),on_delete=models.CASCADE,blank=True,null=True)
    sub=models.ForeignKey(PrvSub,verbose_name=_('子类'),on_delete=models.CASCADE,blank=True,null=True)
    name = models.CharField(_("权限名称"), max_length=50)
    dj_content_id=models.IntegerField(_('django_content_type'),blank=True,null=True)   
    actions=models.JSONField(_('可授权的操作'),default=list,blank=True,null=True)    
    url = models.CharField(verbose_name='含正则的URL', max_length=128,blank=True,null=True)
    is_menu = models.BooleanField(_("是否是菜单"), default=False)
    icon = models.CharField(_("图标"), max_length=32, null=True, blank=True)   
   
    remark=models.CharField(_('备注说明'),max_length=50,blank=True,null=True)
    tm=models.DateTimeField(_("创建时间"), auto_now_add=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _('系统功能权限')
        verbose_name_plural = _('企业功能权限')


class CoPrivilege(models.Model):
    company=models.ForeignKey('company.Company',verbose_name=_('企业名称'),on_delete=models.CASCADE)
    privilege=models.ForeignKey(Privilege,verbose_name=_('系统功能权限'),blank=True,null=True,on_delete=models.SET_NULL)     
    actions=models.JSONField(_('授权操作'),default=list,blank=True,null=True)  
    cgroups=models.JSONField(_('授权组别'),default=list,blank=True,null=True)
    users=models.JSONField(_('授权用户'),default=list,blank=True,null=True)
    remark=models.CharField(_('备注说明'),max_length=50,blank=True,null=True)
    tm=models.DateTimeField(_("创建时间"), auto_now_add=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _('企业功能权限')
        verbose_name_plural = _('企业功能权限')





'''
#2021-12-25
import re
from django.shortcuts import HttpResponse,redirect,render
from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
class PermissionMiddleware(MiddlewareMixin):
    """自定义权限分配中间件"""
    def process_request(self,request):
        # 对权限进行校验
        # 1. 当前访问的URL在不在白名单
        for i in settings.WHITE_URL_LIST:
            ret = re.search(i,request.path)
            if ret:
                return None

        # 获取当前用户的所有权限
        user = request.user
        if not user:
            return redirect("login")

        # 获取用户权限列表
        permissions_list = request.session.get("permissions_list")
        if permissions_list:
            for permission in permissions_list:  # 遍历权限列表，匹配当前路径，匹配上放行
                url = permission['url']
                if re.search(f"^{url}",request.path):
                    # 请求子权限路径，父级权限和父级菜单激活样式设置
                    request.show_id = permission["parent_id"]

                    return None

        # 没有匹配上，提示没有权限
        return HttpResponse("没有权限")  
'''











'''
# 身份角色表
class Role(models.Model):
    company=models.ForeignKey('company.Company',verbose_name=_('企业名称'),on_delete=models.CASCADE)
    title = models.CharField(_("角色名称"), max_length=32)
    permission = models.ManyToManyField("Permission")    

    def __str__(self):
        return self.title

    class Meta:
        unique_together = ('company', 'title')



    @classmethod
    def get_cache(cls):
        try:
            cache = cls.cache
        except AttributeError:
            timeout = getattr(settings, 'DJANGO_RBAC_CACHE_TIMEOUT', 60)
            cache = cls.cache = DictCache(timeout)
        return cache


    def get_cached_role(self):
        """
        Optimized lookup of role by id
        """
        cache = self.get_cache()
        if cache.disabled:
            return self
        roles = cache.get(self.ROLES_BY_ID)
        if roles is None or self.id not in roles:
            self.update_cache()
            roles = cache.get(self.ROLES_BY_ID)
        return roles.get(self.id, self)



# 权限表
class Permission(models.Model):
    name = models.CharField(max_length=32, verbose_name=_('权限名'))
    url = models.CharField(
        max_length=300,
        verbose_name=_('权限url地址'),
        null=True,
        blank=True,
        help_text=_('是否给菜单设置一个url地址')
    )
    icon = models.CharField(
        max_length=32,
        verbose_name=_('权限图标'),
        null=True,
        blank=True
    )
    # 指定属于哪个父级权限
    parent = models.ForeignKey(
        'self',
        verbose_name=_('父级权限'),
        null=True,
        blank=True,
        help_text=_('如果添加的是子权限，请选择父权限'),
        on_delete=models.CASCADE
    )

    # 指定属于哪个menu
    menu = models.ForeignKey(to="Menu",verbose_name=_('对应菜单'),blank=True,null=True,on_delete=models.CASCADE)

    def __str__(self):
        return "{parent}{name}".format(name=self.name, parent="%s-->" % self.parent.name if self.parent else '')

    class Meta:
        verbose_name = _('权限表')
        verbose_name_plural = _('权限表')
        ordering = ["id"]
'''
