from datetime import datetime
import jwt
from .models import *
from accounts.models import Usuario
from bson import ObjectId
from django.conf import settings

# Your JWT settings
JWT_SECRET = settings.SECRET_KEY
JWT_ALGORITHM = settings.SIMPLE_JWT['ALGORITHM']
ACCESS_TOKEN_LIFETIME = settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME']
REFRESH_TOKEN_LIFETIME = settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME']
#ACCESS_TOKEN_EXP_DELTA_SECONDS = 3600  # 1 hour
#REFRESH_TOKEN_EXP_DELTA_SECONDS = 86400  # 1 day

import uuid

def generate_jwt_id():
    return str(uuid.uuid4())


def generate_jwt(user, refresh=False):
    jti = generate_jwt_id()
    try:
        access_payload = {
        'typ': 'JWT',
        'alg': JWT_ALGORITHM,
        'email': user.email,
        'exp': datetime.utcnow() + ACCESS_TOKEN_LIFETIME,
        'iat': datetime.utcnow(),
        'token_type': 'access',
        'jti': jti
        }

        access_expires = access_payload['exp']
        access_token = jwt.encode(access_payload, JWT_SECRET, JWT_ALGORITHM)
        
        # Blacklist all previous tokens
        JWTToken.objects.filter(user_id=[ObjectId(user.id)],token_type='access').update(blacklisted=True)
        
        # Save tokens to the database
        JWTToken.objects.create(user_id=[ObjectId(user.id)], token=access_token, token_type='access', expires=access_expires)
    
    except Exception as e:
        print(f"Error: {e}")
        return None
    
    if not refresh:
        try:
            refresh_payload = {
                'typ': 'JWT',
                'alg': JWT_ALGORITHM,
                'email': user.email,
                'exp': datetime.utcnow() + REFRESH_TOKEN_LIFETIME,
                'iat': datetime.utcnow(),
                'token_type': 'refresh',
                'jti': generate_jwt_id()
            }

            refresh_expires = refresh_payload['exp']
            refresh_token = jwt.encode(refresh_payload, JWT_SECRET, JWT_ALGORITHM)
            
            # Blacklist all previous tokens
            JWTToken.objects.filter(user_id=[ObjectId(user.id)],token_type='refresh').update(blacklisted=True)
            
            # Save tokens to the database
            JWTToken.objects.create(user_id=[ObjectId(user.id)], token=refresh_token, token_type='refresh', expires=refresh_expires)
        
        except Exception as e:
            print(f"Error: {e}")
            return None
    
        return access_token, refresh_token
    
    else:
        return access_token


def blacklist_token(token):
    try:
        jwt_token = JWTToken.objects.get(token=token)
        jwt_token.blacklisted = True
        jwt_token.blacklisted_at = datetime.utcnow()
        jwt_token.save()
        return True
    except JWTToken.DoesNotExist:
        return False

def is_token_blacklisted(token):
    try:
        jwt_token = JWTToken.objects.get(token=token)
        return jwt_token.blacklisted
    except JWTToken.DoesNotExist:
        return False

def check_jwt(token):
    ## checks if it is a valid token. If it is, return the type of token
    try:
        payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
        if is_token_blacklisted(token):
            raise jwt.InvalidTokenError("Token has been blacklisted")
        return payload
    except (jwt.ExpiredSignatureError, jwt.InvalidTokenError) as e:
        print(f"Error: {e}")
        return None
    

def refresh_jwt(token):
    try:
        payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
        #print(f"Debug: payload inside Refresh={payload}")
        if is_token_blacklisted(token):
            raise jwt.InvalidTokenError("Token has been blacklisted")
        if payload['token_type'] != 'refresh':
            raise jwt.InvalidTokenError("Invalid token type")
        user = Usuario.objects.get(email=payload['email'])
        #print(f"Debug: user inside Refresh={user}")
        return generate_jwt(user,refresh=True)
    except (jwt.ExpiredSignatureError, jwt.InvalidTokenError) as e:
        print(f"Error: {e}")
        return None

def validate_jwt(token):
    try:
        payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
        #print(f"Debug: payload inside Validate={payload}")
        if is_token_blacklisted(token):
            raise jwt.InvalidTokenError("Token has been blacklisted")
        return payload
    except (jwt.ExpiredSignatureError, jwt.InvalidTokenError) as e:
        print(f"Error: {e}")
        return None
