from csv import writer

from django.contrib import messages
from django.contrib.auth import login, logout
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.mixins import UserPassesTestMixin
from django.db.models import Avg, Count, Q
from django.db.models.functions import Coalesce
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse, reverse_lazy
from django.views.generic import FormView, TemplateView

from .admin_panel_forms import ContactEnquiryStatusForm, CustomerReviewModerationForm, GoogleSettingsForm, HomePageSettingsForm, SEOSettingsForm, WebsiteSettingsForm
from .bootstrap import ensure_admin_superuser
from .models import CabService, ContactEnquiry, CustomerReview, Destination, GalleryImage, GoogleSettings, HomePageSettings, HolidayPackage, SEOSettings, VisitorCounter, WebsiteLikeCounter, WebsiteSettings


class AdminAccessMixin(UserPassesTestMixin):
    login_url = reverse_lazy("admin_login")

    def test_func(self):
        user = self.request.user
        return user.is_authenticated and (user.is_staff or user.is_superuser)

    def handle_no_permission(self):
        if self.request.user.is_authenticated:
            messages.error(self.request, "You do not have permission to access the dashboard.")
        return redirect(f"{reverse('admin_login')}?next={self.request.get_full_path()}")


class AdminLoginView(FormView):
    template_name = "admin_panel/login.html"
    form_class = AuthenticationForm

    def dispatch(self, request, *args, **kwargs):
        ensure_admin_superuser()
        if request.user.is_authenticated and (request.user.is_staff or request.user.is_superuser):
            return redirect("dashboard")
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        user = form.get_user()
        if not (user.is_staff or user.is_superuser):
            messages.error(self.request, "This account does not have dashboard access.")
            return self.form_invalid(form)

        login(self.request, user)
        return redirect(self.get_redirect_url())

    def get_redirect_url(self):
        next_url = self.request.POST.get("next") or self.request.GET.get("next")
        if next_url:
            return next_url
        return reverse("dashboard")


class AdminLogoutView(AdminAccessMixin, TemplateView):
    def get(self, request, *args, **kwargs):
        logout(request)
        return redirect("admin_login")


class DashboardView(AdminAccessMixin, TemplateView):
    template_name = "admin_panel/dashboard.html"

    def post(self, request, *args, **kwargs):
        if request.POST.get("action") == "reset_visitor_counter":
            VisitorCounter.reset_total()
            messages.success(request, "Visitor counter has been reset.")
        return redirect("dashboard")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        enquiries = ContactEnquiry.objects.order_by("-created_at")
        review_summary = CustomerReview.objects.aggregate(
            total_reviews=Coalesce(Count("id"), 0),
            pending_reviews=Coalesce(Count("id", filter=Q(status=CustomerReview.Status.PENDING)), 0),
            approved_reviews=Coalesce(Count("id", filter=Q(status=CustomerReview.Status.APPROVED)), 0),
            rejected_reviews=Coalesce(Count("id", filter=Q(status=CustomerReview.Status.REJECTED)), 0),
            average_rating=Coalesce(Avg("rating", filter=Q(status=CustomerReview.Status.APPROVED)), 0.0),
        )
        latest_reviews = CustomerReview.objects.order_by("-created_at")[:6]
        context.update(
            {
                "page_title": "Dashboard",
                "total_enquiries": enquiries.count(),
                "total_packages": HolidayPackage.objects.count(),
                "total_destinations": Destination.objects.count(),
                "total_gallery_images": GalleryImage.objects.count(),
                "total_cab_services": CabService.objects.count(),
                "total_visitors": VisitorCounter.load().total_count,
                "total_website_likes": WebsiteLikeCounter.load().total_likes,
                "total_reviews": review_summary["total_reviews"],
                "pending_reviews": review_summary["pending_reviews"],
                "approved_reviews": review_summary["approved_reviews"],
                "rejected_reviews": review_summary["rejected_reviews"],
                "average_rating": round(float(review_summary["average_rating"] or 0), 1),
                "recent_enquiries": enquiries[:6],
                "latest_reviews": latest_reviews,
                "status_breakdown": {
                    status[0]: enquiries.filter(status=status[0]).count()
                    for status in ContactEnquiry.Status.choices
                },
                "content_links": [
                    {"title": "Holiday Packages", "icon": "briefcase-business", "url": reverse("admin:travel_holidaypackage_changelist")},
                    {"title": "Destinations", "icon": "map-pinned", "url": reverse("admin:travel_destination_changelist")},
                    {"title": "Gallery", "icon": "images", "url": reverse("admin:travel_galleryimage_changelist")},
                    {"title": "Cab Services", "icon": "car-front", "url": reverse("admin:travel_cabservice_changelist")},
                ],
                "quick_links": [
                    {"title": "Enquiries", "icon": "inbox", "url": reverse("dashboard_enquiries")},
                    {"title": "Review Management", "icon": "star", "url": reverse("dashboard_reviews")},
                    {"title": "Like Management", "icon": "heart", "url": reverse("dashboard_likes")},
                    {"title": "Website Settings", "icon": "settings-2", "url": reverse("dashboard_website_settings")},
                    {"title": "SEO Settings", "icon": "search-check", "url": reverse("dashboard_seo_settings")},
                    {"title": "Google Settings", "icon": "globe", "url": reverse("dashboard_google_settings")},
                    {"title": "Home Page Settings", "icon": "house", "url": reverse("dashboard_home_settings")},
                ],
            }
        )
        return context


class EnquiryManagementView(AdminAccessMixin, TemplateView):
    template_name = "admin_panel/enquiries.html"

    def get_queryset(self):
        queryset = ContactEnquiry.objects.order_by("-created_at")
        query = self.request.GET.get("q", "").strip()
        status = self.request.GET.get("status", "").strip()
        if query:
            queryset = queryset.filter(
                Q(name__icontains=query)
                | Q(phone__icontains=query)
                | Q(email__icontains=query)
                | Q(destination__icontains=query)
                | Q(message__icontains=query)
                | Q(special_request__icontains=query)
            )
        if status:
            queryset = queryset.filter(status=status)
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        queryset = self.get_queryset()
        context.update(
            {
                "page_title": "Enquiries",
                "status_choices": ContactEnquiry.Status.choices,
                "current_query": self.request.GET.get("q", ""),
                "current_status": self.request.GET.get("status", ""),
                "enquiries": queryset[:100],
                "total_enquiries": queryset.count(),
            }
        )
        return context

    def post(self, request, *args, **kwargs):
        delete_id = request.POST.get("delete_id")
        if delete_id:
            enquiry = get_object_or_404(ContactEnquiry, pk=delete_id)
            enquiry.delete()
            messages.success(request, "Enquiry deleted successfully.")
            return redirect(f"{reverse('dashboard_enquiries')}?{request.GET.urlencode()}")

        enquiry_id = request.POST.get("enquiry_id")
        enquiry = get_object_or_404(ContactEnquiry, pk=enquiry_id)
        form = ContactEnquiryStatusForm(request.POST, instance=enquiry)
        if form.is_valid():
            form.save()
            messages.success(request, "Enquiry updated successfully.")
        else:
            messages.error(request, "Could not update the enquiry.")

        return redirect(f"{reverse('dashboard_enquiries')}?{request.GET.urlencode()}")


class ReviewManagementView(AdminAccessMixin, TemplateView):
    template_name = "admin_panel/reviews.html"

    def get_queryset(self):
        queryset = CustomerReview.objects.order_by("-created_at")
        query = self.request.GET.get("q", "").strip()
        status = self.request.GET.get("status", "").strip()

        if query:
            queryset = queryset.filter(
                Q(name__icontains=query)
                | Q(city__icontains=query)
                | Q(email__icontains=query)
                | Q(review__icontains=query)
            )

        if status:
            queryset = queryset.filter(status=status)

        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        queryset = self.get_queryset()
        context.update(
            {
                "page_title": "Review Management",
                "review_status_choices": CustomerReview.Status.choices,
                "current_query": self.request.GET.get("q", ""),
                "current_status": self.request.GET.get("status", ""),
                "reviews": queryset[:100],
                "total_reviews": queryset.count(),
            }
        )
        return context

    def post(self, request, *args, **kwargs):
        delete_id = request.POST.get("delete_id")
        if delete_id:
            review = get_object_or_404(CustomerReview, pk=delete_id)
            review.delete()
            messages.success(request, "Review deleted successfully.")
            return redirect(f"{reverse('dashboard_reviews')}?{request.GET.urlencode()}")

        review_id = request.POST.get("review_id")
        review = get_object_or_404(CustomerReview, pk=review_id)
        form = CustomerReviewModerationForm(request.POST, instance=review)
        if form.is_valid():
            form.save()
            messages.success(request, "Review updated successfully.")
        else:
            messages.error(request, "Could not update the review.")

        return redirect(f"{reverse('dashboard_reviews')}?{request.GET.urlencode()}")


class LikeManagementView(AdminAccessMixin, TemplateView):
    template_name = "admin_panel/likes.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        like_counter = WebsiteLikeCounter.load()
        context.update(
            {
                "page_title": "Like Management",
                "total_website_likes": like_counter.total_likes,
                "website_like_version": like_counter.like_version,
            }
        )
        return context

    def post(self, request, *args, **kwargs):
        if request.POST.get("action") == "reset_website_likes":
            WebsiteLikeCounter.reset_total()
            messages.success(request, "Website likes have been reset successfully.")
        return redirect("dashboard_likes")


class EnquiryExportView(AdminAccessMixin, TemplateView):
    def get(self, request, *args, **kwargs):
        queryset = ContactEnquiry.objects.order_by("-created_at")
        query = request.GET.get("q", "").strip()
        status = request.GET.get("status", "").strip()
        if query:
            queryset = queryset.filter(
                Q(name__icontains=query)
                | Q(phone__icontains=query)
                | Q(email__icontains=query)
                | Q(destination__icontains=query)
                | Q(message__icontains=query)
                | Q(special_request__icontains=query)
            )
        if status:
            queryset = queryset.filter(status=status)

        response = HttpResponse(content_type="text/csv")
        response["Content-Disposition"] = 'attachment; filename="contact_enquiries.csv"'
        csv_writer = writer(response)
        csv_writer.writerow([
            "Name",
            "Mobile Number",
            "Email",
            "Destination",
            "Date Of Travel",
            "Adults",
            "Children",
            "Number Of Nights",
            "Hotel Category",
            "Special Request",
            "Submitted Date",
            "Status",
        ])
        for enquiry in queryset:
            csv_writer.writerow([
                enquiry.name,
                enquiry.phone,
                enquiry.email,
                enquiry.destination,
                enquiry.date_of_travel or "",
                enquiry.adults or "",
                enquiry.children or "",
                enquiry.number_of_nights or "",
                enquiry.get_hotel_category_display() if enquiry.hotel_category else "",
                enquiry.special_request,
                enquiry.created_at.strftime("%Y-%m-%d %H:%M:%S"),
                enquiry.get_status_display(),
            ])
        return response


class SingletonSettingsView(AdminAccessMixin, FormView):
    template_name = "admin_panel/settings.html"
    success_message = "Settings saved successfully."

    def get_instance(self):
        return self.model.load()

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs["instance"] = self.get_instance()
        return kwargs

    def form_valid(self, form):
        form.save()
        messages.success(self.request, self.success_message)
        return HttpResponseRedirect(self.get_success_url())

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update(
            {
                "page_title": self.page_title,
                "page_description": self.page_description,
            }
        )
        return context


class WebsiteSettingsView(SingletonSettingsView):
    form_class = WebsiteSettingsForm
    model = WebsiteSettings
    page_title = "Website Settings"
    page_description = "Update company information, logo, footer text, and social profiles."

    def get_success_url(self):
        return reverse("dashboard_website_settings")


class SEOSettingsView(SingletonSettingsView):
    form_class = SEOSettingsForm
    model = SEOSettings
    page_title = "SEO Settings"
    page_description = "Manage site-wide metadata, canonical URL, and robots preferences."

    def get_success_url(self):
        return reverse("dashboard_seo_settings")


class GoogleSettingsView(SingletonSettingsView):
    form_class = GoogleSettingsForm
    model = GoogleSettings
    page_title = "Google Settings"
    page_description = "Store analytics and verification IDs safely in the database."

    def get_success_url(self):
        return reverse("dashboard_google_settings")


class HomePageSettingsView(SingletonSettingsView):
    form_class = HomePageSettingsForm
    model = HomePageSettings
    page_title = "Home Page Settings"
    page_description = "Edit hero copy and featured destination/package selections."

    def get_success_url(self):
        return reverse("dashboard_home_settings")