
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from django.db import connection
from api import models, serializers
from django.http import JsonResponse
from os import getenv
import redis
import json
import logging


class LineaViewSet(viewsets.ModelViewSet):
    queryset = models.Linea.objects.all()
    serializer_class = serializers.LineaSerializer
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_fields = ['id_operador', 'route_short_name', 'route_long_name', 'vigente']
    ordering_fields = '__all__'

    @action(detail=False, methods=['get'])
    def proto(self, request, pk=None):
        id_paradero = request.GET['id_paradero']

        query = "SELECT json_data \
                from gtfs_posiciones_json \
                where stop_id = %s"

        with connection.cursor() as cursor:
            cursor.execute(query, [ id_paradero ])
            row = cursor.fetchone()

        return JsonResponse(row[0], safe=False)


    @action(detail=False, methods=['get'])
    def paraderos(self, request, pk=None):
        pk = request.GET['id_linea']

        paraderos = models.Paradero.objects \
            .filter(vigente=True, lineaparadero__id_linea=pk) \
            .values('id_paradero','stop_lat','stop_lon','stop_name') \
            .all()
        return JsonResponse(list(paraderos), safe=False)


    # @action(detail=False, methods=['get'])
    def ___buses(self, request, pk=None):
        pk = request.GET['id_linea']

        # 1. obtener todas los paraderos de redis
        # 2. consultar en cada paradero si hay una linea que corresponda a la consultada
        # 3. si existe se agrega el vehiculo

        db_host = getenv('DB_REDIS_HOST')
        db_port = getenv('DB_REDIS_PORT')
        r = redis.Redis(host=db_host, port=db_port, decode_responses=True)

        fileproto = r.get('fileproto')
        paraderos_redis = r.keys('stop_id:*')
        object_buses = {}
        for key_paradero in paraderos_redis:
            string_trayectos = r.get(key_paradero)
            array_trayectos = json.loads(string_trayectos)

            for trayecto in array_trayectos:
                patente = trayecto['vehicle_license_plate']
                id_linea = f"{trayecto['route_id']}-{trayecto['direction_id']}"

                if id_linea == pk and key_paradero == 'stop_id:none':
                    print(trayecto, flush=True)
                    object_buses[patente] = {
                        'Patente_vehiculo': trayecto["vehicle_license_plate"],
                        'latitude': trayecto["latitude"],
                        'longitude': trayecto["longitude"],
                        'speed': trayecto["speed"]
                    }

                if id_linea == pk and patente not in object_buses:
                    object_buses[patente] = {
                        'Patente_vehiculo': trayecto["vehicle_license_plate"],
                        'latitude': trayecto["latitude"],
                        'longitude': trayecto["longitude"],
                        'speed': trayecto["speed"]
                    }

        array_buses = []
        for patente in object_buses:
            array_buses.append(object_buses[patente])
        
        return Response({
            'fileproto': fileproto,
            'buses': array_buses
        })



    @action(detail=False, methods=['get'])
    def buses(self, request, pk=None):
        pk = request.GET['id_linea']

        db_host = getenv('DB_REDIS_HOST')
        db_port = getenv('DB_REDIS_PORT')
        r = redis.Redis(host=db_host, port=db_port, decode_responses=True)
    
        paraderos = models.Paradero.objects \
            .filter(vigente=True, lineaparadero__id_linea=pk) \
            .values('id_paradero') \
            .all()

        fileproto = r.get('fileproto')
        obj_buses = {}
        array_buses = []
        for p in paraderos:
            key = f'stop_id:{p["id_paradero"]}'
            data = r.get(key)

            if data != None:
                array_trayectos = json.loads(data)
                for trayecto in array_trayectos:
                    key_route = f'{trayecto["route_id"]}-{trayecto["direction_id"]}'
                    if key_route == pk:
                        patente = trayecto["vehicle_license_plate"]
                        if patente not in obj_buses:
                            obj_buses[patente] = {
                                'Patente_vehiculo': trayecto["vehicle_license_plate"],
                                'latitude': trayecto["latitude"],
                                'longitude': trayecto["longitude"],
                                'speed': trayecto["speed"]
                            }

            key = f'stop_id:none'
            data = r.get(key)

            if data != None:
                array_trayectos = json.loads(data)
                for trayecto in array_trayectos:
                    key_route = f'{trayecto["route_id"]}-{trayecto["direction_id"]}'
                    if key_route == pk:
                        patente = trayecto["vehicle_license_plate"]
                        if (patente not in obj_buses) or (patente in obj_buses and obj_buses[patente]['longitude'] == 0 and obj_buses[patente]['latitude'] == 0):
                            obj_buses[patente] = {
                                'Patente_vehiculo': trayecto["vehicle_license_plate"],
                                'latitude': trayecto["latitude"],
                                'longitude': trayecto["longitude"],
                                'speed': trayecto["speed"]
                            }
        
        for patente in obj_buses:
            array_buses.append(obj_buses[patente])
        
        return JsonResponse({
            'fileproto': fileproto,
            'buses': array_buses
        }, safe=False)


    @action(detail=False, methods=['get'])
    def buses_proto(self, request, pk=None):
        pk = request.GET['id_linea']

        linea = models.Linea.objects \
            .filter(id_linea=pk) \
            .first()

        detalle_buses = []
        paraderos = models.Paradero.objects \
            .filter(vigente=True, lineaparadero__id_linea=pk) \
            .values('id_paradero') \
            .all()

        query = "SELECT json_data \
                from gtfs_posiciones_json \
                where stop_id = %s"

        for p in paraderos:
            id_paradero = p['id_paradero']

            with connection.cursor() as cursor:
                cursor.execute(query, [ id_paradero ])
                datajson = cursor.fetchone()

            if datajson != None:
                buses = list(filter(lambda rowjson: rowjson['Descripcion'] == linea.route_short_name, datajson[0]))
                for bus in buses:
                    for llegada in bus['Llegadas']:
                        data_bus = {
                            'patente': llegada['patente'],
                            'estimada_gps': llegada['EstimadaGPS'],
                            'distancia_gps': llegada['DistanciaGPS'],
                        }
                        detalle_buses.append(data_bus)

        return JsonResponse(detalle_buses, safe=False)


    @action(detail=False, methods=['get'])
    def count(self, request, pk=None):

        queryset = models.Linea.objects.all()

        if 'vigente' in request.GET and request.GET['vigente'] == '1':
            queryset = queryset.filter(vigente=True)

        if 'vigente' in request.GET and request.GET['vigente'] == '0':
            queryset = queryset.filter(vigente=False)
        
        return JsonResponse({ 'count': queryset.count() })


    @action(detail=False, methods=['get'])
    def count_buses(self, request, pk=None):

        query = "SELECT \
            l.route_short_name, \
            (select count(distinct vehicle_license_plate) \
                from gtfs_posiciones as gp \
                where (trim(gp.route_id)||'-'||trim(gp.direction_id::varchar)) = l.id_linea \
            ) as count \
            from linea l \
            where \
            (select count(distinct vehicle_license_plate) from gtfs_posiciones as gp where \
            (trim(gp.route_id)||'-'||trim(gp.direction_id::varchar)) = l.id_linea)>0"

        with connection.cursor() as cursor:
            cursor.execute(query)
            result = cursor.fetchall()

        data = []
        for row in result:
            data.append({
                'route_short_name': row[0],
                'count': row[1]
            })
        
        return JsonResponse(data, safe=False)


    


    @action(detail=False, methods=['get'])
    def count_buses_recorridos_old(self, request, pk=None):
        query = "select count(distinct vehicle_license_plate) from gtfs_posiciones"

        with connection.cursor() as cursor:
            cursor.execute(query)
            result = cursor.fetchone()

        return JsonResponse({ 'count': result[0] })
    

    @action(detail=False, methods=['get'])
    def count_lineas_correctas(self, request, pk=None):
        query = """
                SELECT 'Total Rutas correctas' AS titulo, COUNT(*) - (
                    SELECT COUNT(*) AS cantidad 
                    FROM gtfs_validaciones gv 
                    WHERE id_gtfs IN (
                        SELECT id_gtfs 
                        FROM gtfs_archivo 
                        WHERE NOT vigente
                    )
                ) AS cantidad 
                FROM linea 
                WHERE vigente

                UNION

                SELECT 'Total Rutas con Inconsistencias' AS titulo, COUNT(*) AS cantidad 
                FROM gtfs_validaciones gv 
                WHERE id_gtfs IN (
                    SELECT id_gtfs 
                    FROM gtfs_archivo 
                    WHERE vigente
                )
                """

        try:
            with connection.cursor() as cursor:
                cursor.execute(query)
                result = cursor.fetchall()

            data = []
            for row in result:
            # Cada 'row' es una tupla con dos elementos: titulo y cantidad
                data.append({
                    'titulo': row[0],
                    'cantidad': row[1]
                })

            return JsonResponse(data, safe=False)  # Usar safe=False para permitir objetos no diccionario en la raíz
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=400)
    



    @action(detail=False, methods=['get'])
    def count_buses_recorridos(self, request, pk=None):
  
        db_host = getenv('DB_REDIS_HOST')
        db_port = getenv('DB_REDIS_PORT')
        r = redis.Redis(host=db_host, port=db_port, decode_responses=True)
        key = f'stop_id:none'
        data = r.get(key)      
        data = json.loads(data)
        unique_vehicle_plates = set(item["vehicle_license_plate"] for item in data)        
        count_unique_vehicle_plates = len(unique_vehicle_plates)         
        return JsonResponse({ 'count': count_unique_vehicle_plates })
    
    
    @action(detail=False, methods=['get'])
    def count_rutas_buses(self, request, pk=None):
  
        db_host = getenv('DB_REDIS_HOST')
        db_port = getenv('DB_REDIS_PORT')
        r = redis.Redis(host=db_host, port=db_port, decode_responses=True)
        key = f'stop_id:none'
        data = r.get(key)      
        data = json.loads(data)
        unique_route_direction = set(
            (item["route_id"], item["direction_id"]) for item in data
        ) 
        count_unique_route_direction = len(unique_route_direction)              
        return JsonResponse({ 'count': count_unique_route_direction })
    
   