import traceback

from datetime import datetime, timedelta
from decouple import config
from flask import request, jsonify
from functools import wraps
from jwt import encode, decode, ExpiredSignatureError, InvalidSignatureError

from lib.Stech import Logger, Stech
from src.models.recuperautos.UsuariosApp import UsuariosApp

def expire_date(days: int):
    now = datetime.now()
    new_date = now + timedelta(days)
    return new_date

def write_token(data: dict):
    token = encode(payload={**data, 'exp': expire_date(int(config('EXPIRE_DATE'))) }, key=config('SECRET_KEY'), algorithm='HS256')
    return token.encode('UTF-8')

def verify_user_fcm(func):
    @wraps(func)
    def decorador(*args, **kwargs):
        session = Stech.get_session(config('ENVIRONMENTS'))
        try:
            fcm_token = request.headers['Fcm-Token']
            email = request.json['email']

            # Verificar si el usuario existe antes de la actualización
            user_exists = session.query(UsuariosApp).filter(UsuariosApp.email_userapp == email).filter(UsuariosApp.fcm_userapp == fcm_token).first()
            if user_exists:
                return func()
            else:
                raise ValueError("Datos incorrectos o correo electrónico faltante en la solicitud")
        
        except ValueError as ex:
            Logger.add_to_log("error", str(ex))
            Logger.add_to_log("error", traceback.format_exc())
            session.rollback()
            response = jsonify(
                {
                    'message': str(ex), 
                }
            )
            return response, 401
        except Exception as ex:
            Logger.add_to_log("error", str(ex))
            Logger.add_to_log("error", traceback.format_exc())
            session.rollback()
            response = jsonify(
                {
                    'message': str(ex), 
                }
            )
            return response, 401
    
    return decorador

def verify_token(func):
    @wraps(func)
    def decorador(*args, **kwargs):
        secret = config('SECRET_KEY')
        try:
            encoded_token = request.headers['token']
            if ((len(encoded_token) > 0) and (encoded_token.count('.') <= 3)):
                try:
                    decode(encoded_token, secret, algorithms=["HS256"])
                    return func()
                except (ExpiredSignatureError, InvalidSignatureError) as ex:
                    response = jsonify({'message': 'Unauthorized', 'error': str(ex)})
                    return response, 401
        except Exception as ex:
            response = jsonify(
                {
                    'message': 'Unauthorized', 
                    'error': str(ex)
                }
            )
            return response, 401
        
        except:
            response = jsonify(
                {
                    'message': 'Unauthorized',
                    'error': str(ex)
                }
            )
            return response, 401
    return decorador


