from threading import local
from django.shortcuts import render

from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from Models.Localidad import Localidad
from Models.Provincia import Provincia
from .serializers import LocalidadSerializer

class LocalidadViewSet(viewsets.ViewSet):
    @action(detail=False, methods=['get'], url_path='list_locality')
    def list_locality(self, request):
        # Optimization: Fetch all data in a single query using values()
        # This avoids Model instantiation overhead and manual looping in Python
        localidades = Localidad.objects.select_related('provincia').values(
            'id', 'nombre', 'codigo_postal', 'provincia', 'provincia__nombre'
        )
        
        # We can rename keys in python, but it's still a loop. 
        # However, it's faster than the previous approach.
        # Ideally, frontend should accept 'provincia__nombre' or we alias it if DB supports (Django 3.2+ supports aliases in values?)
        # For compatibility and speed, let's just map it quickly or send as is if frontend allows.
        # User wants speed.
        
        # Let's try to do a list comprehension which is faster than append loop
        data = [
            {
                'id': loc['id'],
                'nombre': loc['nombre'],
                'codigo_postal': loc['codigo_postal'],
                'provincia_id': loc['provincia'], # values('provincia') returns the ID
                'provincia': loc['provincia__nombre']
            }
            for loc in localidades
        ]
        
        return Response(data)

    @swagger_auto_schema(
        operation_description="Devuelve una localidad por su ID.",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'id': openapi.Schema(type=openapi.TYPE_INTEGER, description='ID de la localidad')
            },
            required=['id']
        ),
        responses={
            200: openapi.Response('Localidad', LocalidadSerializer),
            400: 'Solicitud incorrecta',
            404: 'Localidad no encontrada'
        }
    )
    @action(detail=False, methods=['post'], url_path='get_locality_by_id')
    def get_locality_by_id(self, request):
        localidad_id = request.data.get('id')
        if not localidad_id:
            return Response({"error": "Se requiere el id de la localidad"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            localidad = Localidad.objects.get(id=localidad_id)
        except Localidad.DoesNotExist:
            return Response({"error": "Localidad no encontrada"}, status=status.HTTP_404_NOT_FOUND)
        serializer = LocalidadSerializer(localidad)
        data = serializer.data
        provincia_id = getattr(localidad, 'provincia_id', None)
        provincia_nombre = None
        if provincia_id:
            provincia = Provincia.objects.filter(id=provincia_id).first()
            provincia_nombre = provincia.nombre if provincia else None
        data['provincia'] = provincia_nombre
        return Response(data)

    @swagger_auto_schema(
        operation_description="Devuelve la localidad y su provincia a partir del código postal.",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'codigo_postal': openapi.Schema(type=openapi.TYPE_STRING, description='Código postal')
            },
            required=['codigo_postal']
        ),
        responses={
            200: 'Localidad y provincia',
            400: 'Solicitud incorrecta',
            404: 'No encontrado'
        }
    )
    @action(detail=False, methods=['post'], url_path='get_locality_by_postal_code')
    def get_locality_by_postal_code(self, request):
        codigo_postal = request.data.get('codigo_postal')
        if not codigo_postal:
            return Response({"error": "Se requiere el código postal"}, status=status.HTTP_400_BAD_REQUEST)

        qs = Localidad.objects.filter(codigo_postal=codigo_postal)
        if not qs.exists():
            return Response({"error": "No se encontraron localidades para ese código postal"}, status=status.HTTP_404_NOT_FOUND)

        localidad = qs.first()
        provincia_id = getattr(localidad, 'provincia_id', None)
        provincia_nombre = None
        if provincia_id:
            provincia = Provincia.objects.filter(id=provincia_id).first()
            provincia_nombre = provincia.nombre if provincia else None

        data = {
            "localidad": {
                "id": localidad.id,
                "nombre": localidad.nombre,
                "codigo_postal": localidad.codigo_postal
            },
            "provincia": {
                "id": provincia_id,
                "nombre": provincia_nombre
            }
        }
        return Response(data, status=status.HTTP_200_OK)