from django.contrib import messages
from django.db.models import Q
from django.shortcuts import get_object_or_404, redirect
from django.utils import timezone
from django.views.generic import CreateView, DetailView, ListView, UpdateView, View

from apps.core.permissions.mixins import RimsAccessMixin
from apps.core.permissions.roles import UserRole
from apps.rims.fleet.forms import (
    MaintenanceRecordForm,
    TripLogForm,
    VehicleBookingForm,
    VehicleForm,
)
from apps.rims.fleet.models import MaintenanceRecord, TripLog, Vehicle, VehicleBooking


class FleetAdminMixin(RimsAccessMixin):
    allowed_roles = (UserRole.ADMIN, UserRole.GRANTS_MANAGER, UserRole.PROGRAMME_OFFICER)


class FleetStaffMixin(RimsAccessMixin):
    allowed_roles = tuple(r.value for r in UserRole)


# --- Vehicles ---

class VehicleListView(FleetAdminMixin, ListView):
    model = Vehicle
    template_name = "fleet/vehicle_list.html"
    context_object_name = "vehicles"
    paginate_by = 20

    def get_queryset(self):
        qs = Vehicle.objects.select_related("assigned_driver")
        q = (self.request.GET.get("q") or "").strip()
        if q:
            qs = qs.filter(
                Q(registration__icontains=q) | Q(make__icontains=q) | Q(model__icontains=q)
            )
        status = self.request.GET.get("status")
        if status:
            qs = qs.filter(status=status)
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["status_choices"] = Vehicle.Status.choices
        return ctx

    def get_template_names(self):
        if getattr(self.request, "htmx", False):
            return ["fleet/partials/vehicle_list_results.html"]
        return super().get_template_names()


class VehicleDetailView(FleetAdminMixin, DetailView):
    model = Vehicle
    template_name = "fleet/vehicle_detail.html"
    context_object_name = "vehicle"

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["recent_bookings"] = self.object.bookings.select_related("requested_by").order_by("-departure_datetime")[:10]
        ctx["maintenance_records"] = self.object.maintenance_records.order_by("-date")[:10]
        return ctx


class VehicleCreateView(FleetAdminMixin, CreateView):
    model = Vehicle
    form_class = VehicleForm
    template_name = "fleet/vehicle_form.html"

    def get_success_url(self):
        from django.urls import reverse
        return reverse("rims_fleet:vehicle_detail", kwargs={"pk": self.object.pk})


class VehicleUpdateView(FleetAdminMixin, UpdateView):
    model = Vehicle
    form_class = VehicleForm
    template_name = "fleet/vehicle_edit.html"

    def get_success_url(self):
        from django.urls import reverse
        return reverse("rims_fleet:vehicle_detail", kwargs={"pk": self.object.pk})


# --- Bookings ---

class BookingListView(FleetAdminMixin, ListView):
    model = VehicleBooking
    template_name = "fleet/booking_list.html"
    context_object_name = "bookings"
    paginate_by = 20

    def get_queryset(self):
        qs = VehicleBooking.objects.select_related("vehicle", "requested_by", "approved_by")
        status = self.request.GET.get("status")
        if status:
            qs = qs.filter(status=status)
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["status_choices"] = VehicleBooking.Status.choices
        return ctx

    def get_template_names(self):
        if getattr(self.request, "htmx", False):
            return ["fleet/partials/booking_list_results.html"]
        return super().get_template_names()


class BookingCreateView(FleetStaffMixin, CreateView):
    model = VehicleBooking
    form_class = VehicleBookingForm
    template_name = "fleet/booking_form.html"

    def form_valid(self, form):
        form.instance.requested_by = self.request.user
        messages.success(self.request, "Vehicle booking request submitted.")
        return super().form_valid(form)

    def get_success_url(self):
        from django.urls import reverse
        return reverse("rims_fleet:booking_list")


class BookingApproveView(FleetAdminMixin, View):
    def post(self, request, pk):
        booking = get_object_or_404(VehicleBooking, pk=pk)
        action = request.POST.get("action")
        if action == "approve":
            booking.status = VehicleBooking.Status.APPROVED
            booking.approved_by = request.user
            booking.approved_at = timezone.now()
            booking.save(update_fields=["status", "approved_by", "approved_at"])
            messages.success(request, "Booking approved.")
        elif action == "reject":
            booking.status = VehicleBooking.Status.REJECTED
            booking.save(update_fields=["status"])
            messages.warning(request, "Booking rejected.")
        from django.urls import reverse
        return redirect(reverse("rims_fleet:booking_list"))


# --- Trip Logs ---

class TripLogCreateView(FleetAdminMixin, CreateView):
    model = TripLog
    form_class = TripLogForm
    template_name = "fleet/trip_log_form.html"

    def dispatch(self, request, *args, **kwargs):
        self.booking = get_object_or_404(VehicleBooking, pk=kwargs["booking_pk"])
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        form.instance.booking = self.booking
        self.booking.status = VehicleBooking.Status.IN_PROGRESS
        self.booking.save(update_fields=["status"])
        messages.success(self.request, "Trip log created.")
        return super().form_valid(form)

    def get_success_url(self):
        from django.urls import reverse
        return reverse("rims_fleet:booking_list")


# --- Maintenance ---

class MaintenanceListView(FleetAdminMixin, ListView):
    model = MaintenanceRecord
    template_name = "fleet/maintenance_list.html"
    context_object_name = "records"
    paginate_by = 20

    def get_queryset(self):
        return MaintenanceRecord.objects.select_related("vehicle", "created_by")


class MaintenanceCreateView(FleetAdminMixin, CreateView):
    model = MaintenanceRecord
    form_class = MaintenanceRecordForm
    template_name = "fleet/maintenance_form.html"

    def dispatch(self, request, *args, **kwargs):
        self.vehicle = get_object_or_404(Vehicle, pk=kwargs["vehicle_pk"])
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        form.instance.vehicle = self.vehicle
        form.instance.created_by = self.request.user
        if form.instance.next_due_date:
            self.vehicle.next_service_date = form.instance.next_due_date
            self.vehicle.save(update_fields=["next_service_date"])
        messages.success(self.request, "Maintenance record saved.")
        return super().form_valid(form)

    def get_success_url(self):
        from django.urls import reverse
        return reverse("rims_fleet:vehicle_detail", kwargs={"pk": self.vehicle.pk})
