import csv

from django.contrib import messages
from django.core.paginator import Paginator
from django.db.models import Q
from django.http import HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse_lazy
from django.views import View
from django.views.decorators.http import require_POST

from apps.core.crud import BaseDeleteView
from apps.core.mixins import EditeurRequiredMixin, safe_next
from apps.core.ratelimit import ratelimit

from .forms import ContactForm, SubscribeForm
from .models import Message, Subscriber

# --- Public -------------------------------------------------------------------


@ratelimit("contact", 5)
def contact(request):
    form = ContactForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request, "Merci ! Votre message a bien été envoyé. Nous vous répondrons rapidement.")
        return redirect("public:contact")
    return render(request, "public/contact.html", {"form": form})


@require_POST
@ratelimit("newsletter", 10)
def subscribe(request):
    form = SubscribeForm(request.POST)
    wants_json = request.headers.get("Accept", "").startswith("application/json")
    if form.is_valid():
        sub, created = Subscriber.objects.get_or_create(email=form.cleaned_data["email"].lower())
        if not created and not sub.is_active:
            sub.is_active = True
            sub.save(update_fields=["is_active", "updated_at"])
        msg, ok = "Merci ! Vous êtes inscrit(e) à notre newsletter.", True
    else:
        msg, ok = "Adresse email invalide.", False
    if wants_json:
        return JsonResponse({"success": ok, "message": msg}, status=200 if ok else 422)
    (messages.success if ok else messages.error)(request, msg)
    return redirect(safe_next(request, "/") + "#newsletter")


# --- Back-office --------------------------------------------------------------

class MessageListView(EditeurRequiredMixin, View):
    def get(self, request):
        qs = Message.objects.all()
        if request.GET.get("filtre") == "non-lus":
            qs = qs.filter(lu=False)
        if q := request.GET.get("q"):
            qs = qs.filter(Q(nom__icontains=q) | Q(email__icontains=q) | Q(sujet__icontains=q) | Q(message__icontains=q))
        page = Paginator(qs, 20).get_page(request.GET.get("page"))
        return render(request, "backoffice/contact/messages.html", {"page_obj": page})


class MessageDetailView(EditeurRequiredMixin, View):
    def get(self, request, pk):
        msg = get_object_or_404(Message, pk=pk)
        if not msg.lu:
            msg.lu = True
            msg.save(update_fields=["lu", "updated_at"])
        return render(request, "backoffice/contact/message_detail.html", {"msg": msg})

    def post(self, request, pk):
        msg = get_object_or_404(Message, pk=pk)
        msg.lu = False
        msg.save(update_fields=["lu", "updated_at"])
        messages.info(request, "Message marqué comme non lu.")
        return redirect("contact:message-list")


class MessageDeleteView(EditeurRequiredMixin, BaseDeleteView):
    model = Message
    success_url = reverse_lazy("contact:message-list")
    success_message = "Message supprimé."


class SubscriberListView(EditeurRequiredMixin, View):
    def get(self, request):
        qs = Subscriber.objects.all()
        if q := request.GET.get("q"):
            qs = qs.filter(email__icontains=q)
        if request.GET.get("export") == "csv":
            resp = HttpResponse(content_type="text/csv; charset=utf-8")
            resp["Content-Disposition"] = 'attachment; filename="abonnes-newsletter.csv"'
            w = csv.writer(resp)
            w.writerow(["email", "actif", "inscrit_le"])
            for s in qs.filter(is_active=True):
                w.writerow([s.email, "oui", s.created_at.strftime("%Y-%m-%d %H:%M")])
            return resp
        page = Paginator(qs, 30).get_page(request.GET.get("page"))
        return render(request, "backoffice/contact/subscribers.html", {
            "page_obj": page,
            "active_count": Subscriber.objects.filter(is_active=True).count(),
        })


class SubscriberToggleView(EditeurRequiredMixin, View):
    def post(self, request, pk):
        s = get_object_or_404(Subscriber, pk=pk)
        s.is_active = not s.is_active
        s.save(update_fields=["is_active", "updated_at"])
        return redirect(safe_next(request, "/admin/newsletter/"))


class SubscriberDeleteView(EditeurRequiredMixin, BaseDeleteView):
    model = Subscriber
    success_url = reverse_lazy("contact:subscriber-list")
    success_message = "Abonné supprimé."
