from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.permissions import IsAdminUser
from django.contrib.auth import authenticate
from .models import Vehicle, VehicleType
from .serializers import VehicleSerializer, VehicleTypeSerializer
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from .models import Vehicle, VehicleAssignment
from accounts.models import Device
from django.utils import timezone
from rest_framework.exceptions import NotFound, PermissionDenied


class ListInactiveVehiclesView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        inactive_vehicles = Vehicle.objects.filter(status=False)
        vehicle_data = [
            {
                "id": vehicle.id,  # type: ignore
                "vehicle_type": vehicle.vehicle_type.vehicle_type,
                "plate_number": vehicle.plate_number,
            }
            for vehicle in inactive_vehicles
        ]

        return Response(
            {
                "status": 1,
                "message": "Inactive vehicles retrieved successfully.",
                "data": vehicle_data,
            },
            status=status.HTTP_200_OK,
        )


class AssignVehicleView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def post(self, request, vehicle_id):
        driver = request.user
        device_token = request.data.get("device_token")

        if not device_token:
            return Response(
                {"status": 0, "message": "Device token is required."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            vehicle = Vehicle.objects.get(id=vehicle_id)
        except Vehicle.DoesNotExist:
            return Response({"status": 0, "message": "Vehicle not found."})

        if vehicle.status:
            return Response(
                {"status": 0, "message": "This vehicle is already assigned."},
                status=status.HTTP_200_OK,
            )

        vehicle.set_active(driver)

        # Save or update the device token
        Device.objects.update_or_create(
            user=driver,
            defaults={"device_token": device_token},
        )

        return Response(
            {"status": 1, "message": "Vehicle assigned to driver successfully."},
            status=status.HTTP_200_OK,
        )


class ReleaseVehicleView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def post(self, request, vehicle_id):
        driver = request.user

        try:
            vehicle_assignment = VehicleAssignment.objects.get(
                vehicle_id=vehicle_id, driver=driver, active=True
            )
        except VehicleAssignment.DoesNotExist:
            return Response(
                {"status": 0, "message": "Vehicle not assigned to this user"}
            )

        vehicle_assignment.vehicle.set_inactive()
        # Delete the device token
        Device.objects.filter(user=driver).delete()

        return Response(
            {"status": 1, "message": "Vehicle released successfully."},
            status=status.HTTP_200_OK,
        )


class BaseVehicleView(APIView):
    """
    Base view for vehicle-related views.
    """

    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAdminUser]

    def success_response(self, message, data=None):
        response_data = {"status": 1, "message": message}
        if data:
            response_data.update(data)
        return Response(response_data, status=status.HTTP_200_OK)

    def error_response(self, message, status_code=status.HTTP_400_BAD_REQUEST):
        return Response({"status": 0, "message": message}, status=status_code)


class ListVehiclesView(BaseVehicleView):
    """
    View to list all vehicles with optional filters.
    """

    def get(self, request):
        try:
            vehicles = Vehicle.objects.all()
            # Apply filters if any
            filters = request.data
            if filters:
                vehicles = vehicles.filter(**filters)
            serializer = VehicleSerializer(vehicles, many=True)
            return self.success_response(
                "Vehicles retrieved successfully", {"vehicles": serializer.data}
            )
        except Exception as e:
            return self.error_response(str(e))


class AddVehicleView(BaseVehicleView):
    """
    View to add a new vehicle.
    """

    def post(self, request):
        try:
            vehicle_type_id = request.data.get("vehicle_type")
            vehicle_type = VehicleType.objects.get(pk=vehicle_type_id)
            vehicle = Vehicle.objects.create(
                vehicle_type=vehicle_type,
                status=request.data.get("status"),
                plate_number=request.data.get("plate_number"),
                vehicle_pic=request.data.get("vehicle_pic"),
            )
            serializer = VehicleSerializer(vehicle)
            return self.success_response(
                "Vehicle added successfully", {"vehicle": serializer.data}
            )
        except VehicleType.DoesNotExist:
            return self.error_response(
                "Invalid vehicle type ID provided", status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return self.error_response(str(e))


class VehicleDetailView(BaseVehicleView):
    """
    View to retrieve, update, or delete a vehicle.
    """

    def get(self, request, pk):
        try:
            vehicle = Vehicle.objects.get(pk=pk)
            serializer = VehicleSerializer(vehicle)
            return self.success_response(
                "Vehicle retrieved successfully", {"vehicle": serializer.data}
            )
        except Vehicle.DoesNotExist:
            return self.error_response("Vehicle not found", status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return self.error_response(str(e))

    def patch(self, request, pk):
        try:
            vehicle = Vehicle.objects.get(pk=pk)
            vehicle_type_id = request.data.get("vehicle_type")
            vehicle_type = VehicleType.objects.get(pk=vehicle_type_id)
            # Update status if provided, otherwise keep the existing status
            vehicle.status = request.data.get("status", vehicle.status)
            # Update plate number if provided, otherwise keep the existing plate number
            vehicle.plate_number = request.data.get(
                "plate_number", vehicle.plate_number
            )
            vehicle.vehicle_pic = request.data.get("vehicle_pic", vehicle.vehicle_pic)
            vehicle.save()
            serializer = VehicleSerializer(vehicle)
            return self.success_response(
                "Vehicle updated successfully", {"vehicle": serializer.data}
            )
        except (Vehicle.DoesNotExist, VehicleType.DoesNotExist):
            return self.error_response(
                "Vehicle or Vehicle Type not found", status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return self.error_response(str(e))

    def delete(self, request, pk):
        try:
            vehicle = Vehicle.objects.get(pk=pk)
            vehicle.delete()
            return self.success_response("Vehicle successfully removed")
        except Vehicle.DoesNotExist:
            return self.error_response("Vehicle not found", status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return self.error_response(str(e))


class VehicleTypeListView(BaseVehicleView):
    """
    View to list all vehicle types.
    """

    def get(self, request):
        try:
            vehicle_types = VehicleType.objects.all()
            serializer = VehicleTypeSerializer(vehicle_types, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            return self.error_response(str(e))


class VehicleTypeDetailView(BaseVehicleView):
    """
    View to retrieve, update, or delete a vehicle type.
    """

    def get(self, request, pk):
        try:
            vehicle_type = VehicleType.objects.get(pk=pk)
            serializer = VehicleTypeSerializer(vehicle_type)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except VehicleType.DoesNotExist:
            return self.error_response(
                "Vehicle type not found", status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return self.error_response(str(e))

    def patch(self, request, pk):
        try:
            vehicle_type = VehicleType.objects.get(pk=pk)
            serializer = VehicleTypeSerializer(
                vehicle_type, data=request.data, partial=True
            )
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except VehicleType.DoesNotExist:
            return self.error_response(
                "Vehicle type not found", status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return self.error_response(str(e))

    def delete(self, request, pk):
        try:
            vehicle_type = VehicleType.objects.get(pk=pk)
            vehicle_type.delete()
            return Response(
                {"message": "Vehicle type deleted successfully"},
                status=status.HTTP_200_OK,
            )
        except VehicleType.DoesNotExist:
            return self.error_response(
                "Vehicle type not found", status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return self.error_response(str(e))


class AddVehicleTypeView(BaseVehicleView):
    """
    View to add a new vehicle type.
    """

    def post(self, request):
        try:
            serializer = VehicleTypeSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return self.error_response(str(e))
