from django.db import models
from django.core.exceptions import ValidationError
from Clientes.models import Clientes
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import BaseUserManager

import re

class BitacoraErrores(models.Model):
    LEVEL_CHOICES = [
        (1,'Critical'),
        (2,'Error'),
        (3,'Warning'),
        (4,'Info'),
        (5,'Debug'),
    ]
    level = models.PositiveBigIntegerField(choices=LEVEL_CHOICES)
    message = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    traceback = models.TextField(null=True,blank=True)
    view = models.CharField(max_length=150,null=True,blank=True)
    class Meta:
        ordering= ('-timestamp',)
    def __str__(self):
        return f"{self.get_level_display()}: {self.message}"

class Sistema(models.Model):
    nombre_sistema= models.CharField(max_length=100, blank=False,null=False,unique=True)
    version = models.CharField(max_length=25)
    # class Meta:
    #     abstract=True
    def __str__(self):
        return f'{self.nombre_sistema}, Version{self.version}'


class sistemas_por_cliente(models.Model):
    id_sistema= models.ForeignKey(Sistema, related_name='sistema_spc', on_delete=models.CASCADE)
    cliente   = models.ForeignKey(Clientes, related_name='cliente_spc', on_delete=models.CASCADE)
    num_licencias= models.IntegerField(default=1)
    def __str__(self):
        return f'{self.cliente.Nombre}'
    class Meta:
        ordering= ('-cliente','id_sistema')
        unique_together = ('id_sistema', 'cliente')

class DeviceManager(BaseUserManager):
    def generate_unique_username(self,client, device_name, ip_address):
        username = f"Device_{client.RFC}_{device_name}_{ip_address}"        
        username_ = re.sub(r'\W+', '', username)
        if User.objects.filter(username=username_).exists():
            raise ValidationError(f"El Usuario ya existe {username_}")
        return username_

    def create_user(self,client, device_name, device_os, ip_address ):
        user_= User.objects.create_user(
            username=self.generate_unique_username(client,device_name,ip_address)
        ) 
        device =self.model(
            client=client,
            device_name= device_name,
            device_os=device_os,
            ip_address=ip_address,
            username=user_
        )
        device.save()

        Token.objects.create(user=user_)
        DeviceHistory.objects.create(device=device)
        return device

class Device(models.Model):
    client = models.ForeignKey(Clientes,on_delete=models.CASCADE)
    device_name = models.CharField(max_length=255)
    device_os = models.CharField(max_length=255)
    ip_address= models.GenericIPAddressField()    
    token = models.ForeignKey(Token, on_delete=models.CASCADE, blank=True,null=True)    
    username = models.ForeignKey(User, on_delete=models.CASCADE)
    sistema = models.ForeignKey(Sistema,on_delete=models.CASCADE, blank=True, null=True)
    macAddress = models.CharField(max_length=30, blank=True,null=True)
    database = models.CharField(max_length=30, blank=True,null=True)
    #objects = DeviceManager()

    class Meta:
        ordering = ('username',)

    def generate_unique_username(self,client, device_name,ip_address, macAddress):
        #username = f"Device_{client.RFC}_{device_name}_{ip_address}_{macAddress}"
        username = f"Device_{client.RFC}_{device_name}_{macAddress}"
        username_ = re.sub(r'\W+', '', username)

        if User.objects.filter(username=username_).exists():
            return User.objects.get(username=username_)
            #raise ValidationError(f"El Usuario ya existe {username_}")
        obj= User.objects.create_user(
            username=username_
        )
        return obj

    def save(self, *args, **kwargs):
        if not self.pk:
            obj = self.generate_unique_username(self.client,self.device_name, self.ip_address, self.macAddress)
            self.username= obj

            token, created = Token.objects.get_or_create(user=obj)

            self.token=token
            super().save(*args, **kwargs)
            DeviceHistory.objects.create(device=self, ip_address=self.ip_address)

    def __str__(self):
        return f'{self.username}'

class DeviceHistory(models.Model):
    device = models.ForeignKey(Device, on_delete=models.CASCADE)
    first_authentication = models.DateTimeField(auto_now_add=True)
    last_authentication  = models.DateTimeField(auto_now=True)
    ip_address = models.GenericIPAddressField()

class Maquinas_Conectadas(models.Model):
    
    UserName = models.CharField(max_length=255)
    PC_Name  = models.CharField(max_length=255)
    Is64     = models.BooleanField()
    OSversion= models.CharField(max_length=255)
    local_ip = models.CharField(max_length=55)
    public_ip= models.CharField(max_length=55)
    Token    = models.CharField(max_length=50)
    Cliente  = models.CharField(max_length=13)
    class Meta:
        abstract =True