
from django.db import transaction
from django.http import HttpResponse, JsonResponse
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action

from api import models, schemas, serializers
import json
import logging

class ContratoViewSet(viewsets.ModelViewSet):
    queryset = models.Contrato.objects.all()
    serializer_class = serializers.ContratoSerializer
    schema = schemas.ContratoSchema()

    def retrieve(self, request, pk=None):
        data = super().retrieve(request, pk)
        return data

    def create(self, request):
        try:
            with transaction.atomic():
                input = json.loads(request.body)
                persona = models.Persona.objects.filter(rut = input['rut']).first()
                id_tipo_tratamiento = input.get('id_tipo_tratamiento',None)
                if not id_tipo_tratamiento:
                    id_tipo_tratamiento = None
                
                if not persona:
                    persona = models.Persona(
                        rut = input['rut'],
                        dv = input['dv'],
                        nombres = input['nombres'],
                        apellido_a = input.get('apellido_a',None),
                        apellido_b = input.get('apellido_b',None),
                        email = input.get('email',None),
                        id_tipo_tratamiento = id_tipo_tratamiento
                    )
                    persona.save()
                else:
                    persona.nombres = input['nombres']
                    persona.apellido_a = input.get('apellido_a',None)
                    persona.apellido_b = input.get('apellido_b',None)
                    persona.email = input.get('email',None)
                    persona.id_tipo_tratamiento = id_tipo_tratamiento
                    persona.save()
                    cargo = models.TipoCargo.objects.filter(id_cargo=input.get('id_cargo',None)).first()
                    operador=models.Operador.objects.filter(id_operador=input.get('id_operador',None)).first()
                if cargo == None:
                    raise ValueError('Cargo no encontrado')

                Contrato = models.Contrato(
                    rut = persona,
                    id_operador = operador, 
                    desde = input['desde'],
                    hasta = input['hasta']
                )
                Contrato.save()

                if input['clave']:
                    logging.error('Modificar clave de Contrato')
                    Contrato.clave = make_password(input['clave'])
                    Contrato.save()
            
            return Response({
                'rut': persona.rut,
                'dv': persona.dv,
                'nombres': persona.nombres,
                'apellido_a': persona.apellido_a,
                'apellido_b': persona.apellido_b,
                'email': persona.email,
                'login': Contrato.login,
                'vigente': Contrato.vigente,
            })
        
        except ValueError as e:
            transaction.rollback()
            return HttpResponse(str(e), status = 400)
        
        except Exception as e:
            transaction.rollback()
            print(e)
            return HttpResponse(str(e), status = 500)

    def update(self, request, *args, **kwargs):
        input = json.loads(request.body)
        try:
            pk = input['rut']
            with transaction.atomic():

                # validaciones se realiza a nivel del model
                persona = models.Persona.objects.filter(rut = pk).first()
                rol = models.Rol.objects.filter(id_rol = input.get('id_rol')).first()

                Contrato = models.Contrato.objects.filter(rut = pk).first()
                Contrato.vigente = input.get('vigente', False)
                Contrato.superuser = input.get('superuser', False)
                Contrato.id_rol = rol
                Contrato.save()

                if 'clave' in input:
                    logging.error('Modificar clave de Contrato')
                    Contrato.clave = make_password(input['clave'])
                    Contrato.save()
            
            return Response({
                'rut': persona.rut,
                'dv': persona.dv,
                'nombres': persona.nombres,
                'apellido_a': persona.apellido_a,
                'apellido_b': persona.apellido_b,
                'email': persona.email,
                'login': Contrato.login,
                'vigente': Contrato.vigente,
            })
        
        except ValueError as e:
            transaction.rollback()
            return HttpResponse(str(e), status = 400)
        
        except Exception as e:
            transaction.rollback()
            logging.error(e)
            return HttpResponse(str(e), status = 500)

    @action(detail=False, methods=['post'])
    def permisos(self, request):
        input = {}
        if request.body > b'':
            input = json.loads(request.body)

        login = request.jwt_info['login']
        Contrato = models.Contrato.objects.filter(login=login).first()
        escritura = Contrato.superuser == True

        if 'path' in input:
            path = input.get('path')
            aplicacion = models.Aplicacion.objects.filter(path_app=path).first()

            if escritura == False:
                rol_aplicacion = models.RolAplicacion.objects.filter(id_rol=Contrato.id_rol, id_aplicacion=aplicacion.id_aplicacion).first()
                escritura = rol_aplicacion.solo_visualizar == False

            return JsonResponse({
                'path_app': path,
                'nombre_app': aplicacion.nombre_app,
                'escritura': escritura
            })
        else:
            registros = models.RolAplicacion.objects.filter(id_rol=Contrato.id_rol)
            aplicaciones = []
            for registro in registros:
                if registro.id_aplicacion.vigente:
                    rol_app = models.RolAplicacion.objects.filter(id_rol=registro.id_rol, id_aplicacion=registro.id_aplicacion).first()
                    
                    aplicaciones.append({
                        'path_app': registro.id_aplicacion.path_app,
                        'nombre_app': registro.id_aplicacion.nombre_app,
                    })

            return JsonResponse({ "aplicaciones": aplicaciones })
