import structlog
from typing import Any

from django.db import transaction
from django.db.models import QuerySet
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.views import generic
from django.views.decorators.http import require_http_methods

from .models import Teil

logger = structlog.get_logger(__name__)


DEFAULT_TEILE_NUMBER = 10

class TeileListView(generic.ListView):
    template_name = "collector/index.html"
    context_object_name = "teile_list"

    def get_queryset(self) -> QuerySet:
        return Teil.objects.order_by("-modified")

    def get_context_data(self, **kwargs) -> dict[str, Any]:
        context = super().get_context_data(**kwargs)
        context["default_teile_number"] = DEFAULT_TEILE_NUMBER

        return context


class IndexView(TeileListView):
    def get_queryset(self) -> QuerySet:
        return super().get_queryset()[:10]


class DetailView(generic.DetailView):
    model = Teil
    template_name = "collector/detail.html"

    def get_context_data(self, **kwargs) -> dict[str, Any]:
        context = super().get_context_data(**kwargs)
        context["default_teile_number"] = DEFAULT_TEILE_NUMBER

        return context


@require_http_methods(["POST"])
def enter(request: HttpRequest) -> HttpResponse:
    try:
        # if .create() failed, the transaction is rolled back and we are in a
        # clean (database) state to handle exceptions
        with transaction.atomic():
            teil = Teil.objects.create(name=request.POST["new_name"])
    except Exception:
        logger.warning("Teil already existed")
    else:
        logger.info("New Teil entered", teil_id=teil.pk)

    return HttpResponseRedirect(reverse("collector:list"))