# -*- encoding: utf-8 -*-

import logging

from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import PermissionsMixin

from .managers import DiscordUserOAuth2Manager

log = logging.getLogger(__name__)


class DiscordUser(PermissionsMixin):
    """
    Represents a User authenticated with Discord OAuth2.
    """

    # Discord Attributes

    id = models.PositiveBigIntegerField(
        primary_key=True,
        help_text=_("the user's id")
    )
    username = models.CharField(
        _("username"),
        max_length=32,
        unique=True,
        help_text=_("the user's username, not unique across the platform")
    )
    global_name = models.CharField(
        _("nickname"),
        max_length=32,
        help_text=_("the user's display name, if it is set. For bots, this is the application name")
    )
    avatar = models.CharField(
        _("avatar"),
        max_length=64,
        help_text=_("the user's avatar hash")
    )
    public_flags = models.IntegerField(
        _("public flags"),
        help_text=_("the public flags on a user's account")
    )
    flags = models.IntegerField(
        _("flags"),
        help_text=_("the flags on a user's account")
    )
    locale = models.CharField(
        _("locale"),
        max_length=16,
        help_text=_("the user's chosen language option")
    )
    mfa_enabled = models.BooleanField(
        _("mfa enabled"),
        help_text=_("whether the user has two factor enabled on their account")
    )
    last_login = models.DateTimeField(
        _("last login"),
        default=timezone.now,
        help_text=_("datetime of the previous login")
    )

    # Access Token

    access_token = models.CharField(
        _("access token"),
        max_length=100,
        help_text=_("token for the application to make api calls on behalf of the user.")
    )
    token_expires = models.DateTimeField(
        _("token expires"),
        help_text=_("when to request a new access token.")
    )
    refresh_token = models.CharField(
        _("refresh token"),
        max_length=100,
        help_text=_("token for the application to request a new access token.")
    )

    # Custom Attributes

    class USER_TYPES(models.TextChoices):
        DISCORD_USER = "D", _("discord")
        AUTOMATED_USER = "A", _("automated")

    user_type = models.CharField(
        _("user type"),
        choices=USER_TYPES,
        default=USER_TYPES.DISCORD_USER,
        max_length=32,
        help_text=_("What type of user is this?")
    )

    is_active = models.BooleanField(
        _("active status"),
        default=True,
        help_text=_('Use as a "soft delete" rather than deleting the user.')
    )
    is_staff = models.BooleanField(
        _("staff status"),
        default=False,
        help_text=_("Designates whether the user can log into this admin site.")
    )
    is_superuser = models.BooleanField(
        _("superuser status"),
        default=False,
        help_text=_("Designates whether the user has unrestricted site control.")
    )

    # Object Manager

    objects = DiscordUserOAuth2Manager()

    REQUIRED_FIELDS = []
    USERNAME_FIELD = "username"

    def __str__(self):
        return self.global_name or self.username

    @property
    def avatar_url(self):
        # Default avatar
        if len(self.avatar) <= 1:
            return f"https://cdn.discordapp.com/embed/avatars/{self.avatar}.png"

        # Custom avatar
        return f"https://cdn.discordapp.com/avatars/{self.id}/{self.avatar}.webp?size=128"

    @property
    def password(self):
        return "password"

    @property
    def is_authenticated(self):
        return True

    @property
    def is_anonymous(self):
        return False

    def get_username(self):
        return self.username

    def update(self, raw: dict):

        log.debug("updating user: %s", self.username)

        self.username=raw["username"]
        self.global_name=raw["global_name"]
        self.avatar=raw["avatar"]
        self.public_flags=raw["public_flags"]
        self.flags=raw["flags"]
        self.locale=raw["locale"]
        self.mfa_enabled=raw["mfa_enabled"]
        self.access_token=raw["access_token"]
        self.token_expires=raw["token_expires"]
        self.refresh_token=raw["refresh_token"]

        self.save(force_update=True)


class ServerMember(models.Model):
    """
    A link table, connecting users to servers, and storing their server-specific data.
    """

    id = models.AutoField(primary_key=True)
    user = models.ForeignKey(to=DiscordUser, on_delete=models.CASCADE)
    server = models.ForeignKey(to="home.Server", on_delete=models.CASCADE)
    permissions = models.CharField(max_length=32)
    is_owner = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.server.name} · {self.user}"

    def has_permission(self, flag: int) -> bool:
        """Check that the member has a givern permission.
        https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags
        """
        permissions_int = int(self.permissions)
        return (permissions_int & flag) == flag
