"""
The API views for Centralised File System.
"""

import mimetypes

from django.http import FileResponse
from rest_framework.authentication import (BasicAuthentication,
                                           SessionAuthentication)
from rest_framework.decorators import (authentication_classes,
                                       permission_classes)
from rest_framework.generics import CreateAPIView, UpdateAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication

from centralisedFileSystem.models import File, ScreenPlay, Script
from centralisedFileSystem.serializers import (FileSerializer,
                                               ScreenPlayScriptSerializer,
                                               ScreenPlaySerializer,
                                               ScriptSerializer,
                                               UserScriptsSerializer)


@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
class ScriptView(CreateAPIView):
    '''
    Create view for creating new scripts and uploading a file to it.
    '''
    queryset = Script.objects.all()
    serializer_class = ScriptSerializer

    def get(self, request) -> FileResponse:
        '''
        To download any file of the given script.

        ________________________________________________
        QueryParameters

        script_id   :   id of the script
        type        :   type of file to downlaod
        ________________________________________________

        '''

        if not "script_id" in request.query_params:
            return Response("script_id must be provided in query parameter to Download a script.", status=status.HTTP_400_BAD_REQUEST)

        if not "type" in request.query_params:
            return Response("type must be provided in query parameter to specify the type of file.", status=status.HTTP_400_BAD_REQUEST)

        query_file = File.objects.get(
            script = request.query_params.get("script_id"),
            type = request.query_params.get("type"),
        )

        file_path = query_file.file.path
        file_size = query_file.file.size

        document = open(file_path, 'rb')

        mimetype, _ = mimetypes.guess_type(file_path)

        response = FileResponse(document, content_type=mimetype)
        response['Content-Length'] = file_size
        response['Content-Disposition'] = f"attachment; filename={query_file.script.screenplay.name + '_' + str(query_file)}.{file_path.rsplit('.',1)[1]}"
        return response


@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
class ScreenPlayView(CreateAPIView):
    '''
    For creating new screenplays.
    '''
    queryset = ScreenPlay.objects.all()
    serializer_class = ScreenPlaySerializer

    def get(self, request) -> Response:
        '''
        To get all the scripts of the given script name.

        ________________________________________________
        QueryParameters

        screenplay   :   name of the screenplay
        ________________________________________________

        '''

        if not "screenplay" in request.query_params:
            return Response("screenplay name must be provided in query parameter.", status=status.HTTP_400_BAD_REQUEST)

        queryobject = ScreenPlay.objects.get(
            name = request.query_params.get("screenplay"),
            user = request.user,
        )
        script = UserScriptsSerializer(queryobject)

        return Response(script.data)


@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
class ScreenPlayScriptView(CreateAPIView):
    '''
    For creating a new screenplay with a script and uploading a file to it.
    '''
    queryset = ScreenPlay.objects.all()
    serializer_class = ScreenPlayScriptSerializer


@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
class FileView(CreateAPIView, UpdateAPIView):
    '''
    To upload a file to a script.
    '''
    queryset = File.objects.all()
    serializer_class = FileSerializer

    def get(self, request) -> Response:
        '''
        To get the specified file of a script.

        _____________________________________
        QueryParameters

        script_id   :   script id
        type        :   file type
        _____________________________________
        '''

        if not "script_id" in request.query_params:
            return Response("script_id must be provided in query parameter.", status=status.HTTP_400_BAD_REQUEST)

        if not "type" in request.query_params:
            return Response("type must be provided in query parameter.", status=status.HTTP_400_BAD_REQUEST)

        queryobject = File.objects.get(
            script = request.query_params.get("script_id"),
            type = request.query_params.get("type"),
        )
        serializer = FileSerializer(queryobject)
        return Response(serializer.data)


# @authentication_classes([SessionAuthentication, BasicAuthentication])
# @permission_classes([IsAuthenticated])
class UserScripts(APIView):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request) -> Response:
        '''
        To get all the screenplays along with all of their scripts of the current user.
        '''

        queryset = ScreenPlay.objects.filter(user=request.user)
        scripts = UserScriptsSerializer(queryset, many=True)

        return Response(scripts.data)