import re

from asgiref.sync import async_to_sync
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db import transaction
from django.http import HttpResponse
from django.utils import timezone as dj_timezone
from rest_framework import status
from rest_framework.views import APIView

from core.forms import QueueForm
from core.models import Message, QueuedMessage
from core.util import logs
from mixins.views import ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate

log = logs.get_logger("queue")
_INLINE_TARGET_RE = re.compile(r"^#queue-inline-editor-[A-Za-z0-9_-]+$")


class AcceptMessageAPI(LoginRequiredMixin, APIView):
    def get(self, request, message_id):
        try:
            queued = QueuedMessage.objects.select_related(
                "session",
                "session__identifier",
                "session__user",
            ).get(
                user=request.user,
                id=message_id,
            )
        except QueuedMessage.DoesNotExist:
            return HttpResponse(status=status.HTTP_404_NOT_FOUND)

        ts = async_to_sync(queued.session.identifier.send)(
            queued.text or "",
            [],
        )
        if not ts:
            log.error("Queue accept send failed for queued message %s", queued.id)
            return HttpResponse(status=status.HTTP_502_BAD_GATEWAY)
        sent_ts = (
            int(ts)
            if (ts is not None and not isinstance(ts, bool))
            else int(dj_timezone.now().timestamp() * 1000)
        )

        with transaction.atomic():
            Message.objects.create(
                user=queued.session.user,
                session=queued.session,
                custom_author=queued.custom_author or "BOT",
                text=queued.text,
                ts=sent_ts,
                delivered_ts=sent_ts,
                read_source_service=queued.session.identifier.service,
            )
            queued.delete()

        return HttpResponse(status=status.HTTP_200_OK)


class RejectMessageAPI(LoginRequiredMixin, APIView):
    def get(self, request, message_id):
        try:
            message = QueuedMessage.objects.get(
                user=self.request.user,
                id=message_id,
            )
        except QueuedMessage.DoesNotExist:
            return HttpResponse(status=status.HTTP_404_NOT_FOUND)

        message.delete()

        return HttpResponse(status=status.HTTP_200_OK)


class QueueList(LoginRequiredMixin, ObjectList):
    list_template = "partials/queue-list.html"
    model = QueuedMessage
    page_title = "Approvals Queue"

    list_url_name = "queues"
    list_url_args = ["type"]

    submit_url_name = "queue_create"


class QueueCreate(LoginRequiredMixin, ObjectCreate):
    model = QueuedMessage
    form_class = QueueForm

    submit_url_name = "queue_create"


class QueueUpdate(LoginRequiredMixin, ObjectUpdate):
    model = QueuedMessage
    form_class = QueueForm
    window_content = "mixins/window-content/queue-form-inline.html"

    submit_url_name = "queue_update"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        raw_target = str(self.request.GET.get("hx_target") or "").strip()
        if _INLINE_TARGET_RE.fullmatch(raw_target):
            context["submit_target"] = raw_target
        else:
            context["submit_target"] = "#modals-here"
        context["is_inline_edit"] = context["submit_target"].startswith(
            "#queue-inline-editor-"
        )
        return context


class QueueDelete(LoginRequiredMixin, ObjectDelete):
    model = QueuedMessage
