
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.hashers import check_password, make_password
from django.http import HttpResponse, JsonResponse

from rest_framework.decorators import action, api_view, schema
from project.settings import SECRET_KEY, EMAIL_HOST

from api import models, schemas
from datetime import datetime, timedelta
from decouple import config
import json
import jwt
import logging
import random

from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import get_template

# Views jwt
@csrf_exempt
@action(detail=False, methods=['post','get'])
@api_view(['GET','POST'])
@schema(schemas.AuthSchema())
def jwt_login(request):
    if request.method == 'POST':
        # validar rut y password
        input = json.loads(request.body)
        rut = input['rut'].replace('.','').replace('-','')

        if rut != '0':
            dv = rut[-1].upper()
            rut = rut[:-1]
        
        usuario = None

        if rut == '0' and password == '0':
            usuario = { 'login': '0', 'clave': '0' }
            
            # solo se permite usuario 0 si no existen usuarios vigentes
            count = models.Usuario.objects.filter(vigente = True).count()
            if count > 0:
                return HttpResponse('Acceso no valido', status=400)
        else:
            usuario = models.Usuario.objects.filter(vigente=1, rut__rut=rut, rut__dv=dv).values().first()

            if not check_password(input['password'], usuario['clave']):
                return HttpResponse('Acceso no valido', status=400)

        ahora = datetime.utcnow()
        manana = ahora + timedelta(days=1)
        manana = manana.replace(hour=0, minute=0, second=0, microsecond=0)

        payload = {
            'iat': ahora,
            'exp': manana, # ahora + timedelta(minutes=60),
            'login': usuario['login']
        }
        token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
        return JsonResponse({ 'token': token })

    elif request.method == 'GET':
        return JsonResponse(request.jwt_info)



@csrf_exempt
@action(detail=False, methods=['post'])
@api_view(['POST'])
def recuperar(request):
    input = json.loads(request.body)
    rut = input['rut'].replace('.','').replace('-','')

    dv = rut[-1].upper()
    rut = rut[:-1]

    persona = models.Persona.objects.filter(rut=rut, dv=dv).first()
    usuario = models.Usuario.objects.filter(rut=rut, vigente=True).first()

    if usuario == None or persona == None:
        return HttpResponse('Acceso no valido', status=400)

    if persona.email != input['email'].lower():
        return HttpResponse('Acceso no valido', status=400)

    codigo_aleatorio = random.randint(100000, 999999)
    ahora = datetime.utcnow()
    expira = ahora + timedelta(minutes=5)
    payload = {
        'iat': ahora,
        'exp': expira,
        'rut': f'{persona.rut}',
        'codigo': codigo_aleatorio
    }
    token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
    vinculo = f"{http_referer(request)}/?s={token}#/new-password"

    exito = enviar_correo(persona.email, 'Recuperar acceso', {
        'nombre': f'{persona.nombres} {persona.apellido_a} {persona.apellido_b}',
        'codigo': codigo_aleatorio,
        'vinculo': vinculo
    })

    return JsonResponse({ 'ok': exito, 'HTTP_REFERER': request.META['HTTP_REFERER'] })



@csrf_exempt
@action(detail=False, methods=['post'])
@api_view(['POST'])
def info_token(request):
    input = json.loads(request.body)
    token = input['token']
    try:
        decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        persona = models.Persona.objects.filter(rut=decoded['rut']).first()

        return JsonResponse({
            'nombres': persona.nombres,
            'apellido_a': persona.apellido_a,
            'apellido_b': persona.apellido_b
        })
    except jwt.ExpiredSignatureError:
        return HttpResponse('token ya no es valido', status = 400)
    except jwt.InvalidTokenError:
        return HttpResponse('token es invalido', status = 400)



@csrf_exempt
@action(detail=False, methods=['post'])
@api_view(['POST'])
def nueva_contrasena(request):
    input = json.loads(request.body)
    token = input['token']
    try:
        decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])

        if f"{decoded['codigo']}" != input['codigo']:
            return HttpResponse('código es invalido', status = 400)

        usuario = models.Usuario.objects.filter(rut = decoded['rut']).first()
        if usuario == None:
            return HttpResponse('Usuario no encontrado', status = 400)

        usuario.clave = make_password(input['password'])
        usuario.save()

        return JsonResponse({ 'ok': True })

    except jwt.ExpiredSignatureError:
        return HttpResponse('token ya no es valido', status = 400)
    except jwt.InvalidTokenError:
        return HttpResponse('token es invalido', status = 400)
    except Exception as e:
        logging.error(e)
        return HttpResponse('error al cambiar contraseña', status = 500)



    
def enviar_correo(destinatario, asunto, contenido):
    try:
        template = get_template('correo_recuperar.html')  # Ruta al template del correo
        contenido_renderizado = template.render(contenido)

        mensaje = EmailMultiAlternatives(asunto, '', settings.EMAIL_HOST_USER, [destinatario])
        mensaje.attach_alternative(contenido_renderizado, 'text/html')
        mensaje.send()
        return True
    except Exception as e:
        print(f'EMAIL_HOST: {EMAIL_HOST}', flush=True)
        print(f'ERROR: {e}', flush=True)
        return False




def http_referer(request):
    if 'HTTP_REFERER' in request.META:
        referer = request.META['HTTP_REFERER']
    else:
        protocol = request.scheme
        host = request.META['HTTP_HOST']
        port = request.META['SERVER_PORT']
        referer = f'{protocol}://{host}'
    return referer