import uuid
import os
from pathlib import Path

from django.conf import settings
from django.http import Http404
from django.core.files.storage import FileSystemStorage

from rest_framework import permissions, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from rest_framework.parsers import FileUploadParser

from ichec_django_core.models import FormField
from ichec_django_core.views import (
    SearchableModelViewSet,
    ObjectFileDownloadView,
    OwnerFullOrDjangoModelPermissions,
)

from marinerg_test_access.models import AccessCall, AccessCallFacilityReview
from marinerg_test_access.serializers import (
    AccessCallListSerializer,
    AccessCallDetailSerializer,
    AccessCallCreateSerializer,
    AccessCallFacilityReviewSerializer,
)


class CoordinatorEditOrDjangoModelPermissions(OwnerFullOrDjangoModelPermissions):
    owner_field = "coordinator"


class AccessCallViewSet(SearchableModelViewSet):
    queryset = AccessCall.objects.all()
    serializer_class = AccessCallListSerializer

    serializers = {
        "retrieve": AccessCallDetailSerializer,
        "list": AccessCallListSerializer,
        "create": AccessCallCreateSerializer,
        "update": AccessCallDetailSerializer,
        "partial_update": AccessCallDetailSerializer,
    }

    permission_classes = [
        permissions.IsAuthenticated,
        CoordinatorEditOrDjangoModelPermissions,
    ]

    ordering_fields = ("status",)
    ordering: tuple[str, ...] = ("-closing_date",)
    search_fields = ["title"]

    @action(
        detail=True, url_path="applications_summary", url_name="applications_summary"
    )
    def applications_summary(self, request, pk=None):
        return self.download(request, "applications_summary")


class AccessCallFieldDownloadView(ObjectFileDownloadView):

    model = AccessCall
    permission_classes = [
        permissions.IsAuthenticated,
        CoordinatorEditOrDjangoModelPermissions,
    ]

    def get_file(self):
        if not self.value.template:
            raise Http404
        return self.value.template

    def get_basename(self):
        ext = self.value.template.name.split(".")[-1]
        return f"access_call_{self.value.key}.{ext}"

    def get(self, request, *args, **kwargs):
        self.authenticate(request)
        self.has_permission(request)

        self.object = self.get_object()
        self.value = FormField.objects.get(id=kwargs["value_id"])
        return super(ObjectFileDownloadView, self).get(request, *args, **kwargs)


class AccessCallFieldUploadView(GenericAPIView):

    model = AccessCall
    queryset = AccessCall.objects.all()
    parser_classes = [FileUploadParser]
    permission_classes = [
        permissions.IsAuthenticated,
        CoordinatorEditOrDjangoModelPermissions,
    ]
    extensions = (".odt", ".doc", ".docx", ".pdf")

    def put(self, request, *args, **kwargs):
        value = FormField.objects.get(id=kwargs["value_id"])

        media_root = Path(settings.MEDIA_ROOT)
        instance = self.get_object()
        storage_dir = Path(
            f"{self.model._meta.model_name}/{instance.id}/field_templates"
        )
        os.makedirs(media_root / storage_dir, exist_ok=True)

        filename = request.data["file"].name

        _, ext = os.path.splitext(filename)
        if ext not in self.extensions:
            return Response(
                {"reason": "File extension not supported"},
                status=400,
            )

        file_path = f"{uuid.uuid4()}{ext}"
        written_path = FileSystemStorage(location=media_root / storage_dir).save(
            file_path, request.data["file"]
        )

        value.template.original_file_name = filename
        value.template.name = str(storage_dir / written_path)
        value.save()

        return Response(status=204)


class AccessCallFacilityReviewViewSet(viewsets.ModelViewSet):
    queryset = AccessCallFacilityReview.objects.all().order_by("id")
    serializer_class = AccessCallFacilityReviewSerializer
    permission_classes = [
        permissions.IsAuthenticated,
        permissions.DjangoModelPermissions,
    ]
