import os
from django.conf import settings
from django.http import FileResponse
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiResponse
from sorl.thumbnail import get_thumbnail
from apps.files.models import PostFileModel
from .serializers import (
    PostFileSerializer,
    FileResponseSerializer,
    ErrorResponseSerializer,
)

THUMBNAIL_SIZES = {
    "sx": (64, ".thumb_64.jpg"),
    "sm": (256, ".thumb_256.jpg"),
    "md": (748, ".thumb_748.jpg"),
    "lg": (1024, ".thumb_1024.jpg"),
    "xl": (2048, ".thumb_2048.jpg"),
}


class FileServeView(GenericAPIView):
    """
    API view to serve content files for download or inline viewing.

    Authentication can be provided via:
    1. Authorization header (JWT token)
    2. 'token' query parameter (JWT token)
    """

    # Set permissions as needed
    permission_classes = [IsAuthenticated]
    serializer_class = FileResponseSerializer
    queryset = PostFileModel.objects.all()

    def get_thumbnail_file(self, source_path, size_key):
        """Generates and retrieves the thumbnail file."""
        size, suffix = THUMBNAIL_SIZES.get(size_key, (None, ""))
        if size:
            thumbnail_file = get_thumbnail(source_path, str(size), upscale=False)
            return os.path.abspath(
                os.path.join(settings.MEDIA_ROOT, thumbnail_file.name)
            ), suffix
        return None, ""

    @extend_schema(
        parameters=[
            OpenApiParameter(
                name="d",
                description="Download flag (0 = download, otherwise inline)",
                required=False,
                type=str,
            ),
            OpenApiParameter(
                name="t",
                description="Thumbnail size (sx, sm, md, lg, xl)",
                required=False,
                type=str,
            ),
            OpenApiParameter(
                name="token",
                description="JWT token for authentication (alternative to Authorization header)",
                required=False,
                type=str,
            ),
        ],
        responses={
            200: OpenApiResponse(description="File returned successfully"),
            401: ErrorResponseSerializer,
            404: ErrorResponseSerializer,
            500: ErrorResponseSerializer,
        },
    )
    def get(self, request, file_hash):
        """Handle GET requests for file serving."""
        download = request.query_params.get("d") == "0"
        thumbnail_key = request.query_params.get("t")

        try:
            obj_file = PostFileModel.objects.filter(hash_blake3=file_hash).first()
            if not obj_file:
                return Response(
                    {"error": "File not found"}, status=status.HTTP_404_NOT_FOUND
                )

            file_name = obj_file.name.first().filename
            file_type = obj_file.file_type
            source_file = obj_file.file

            # Use thumbnail if requested and file type is image
            if thumbnail_key and file_type != "image":
                source_file = obj_file.thumbnail

            # Retrieve the requested thumbnail file if applicable
            if thumbnail_key in THUMBNAIL_SIZES:
                thumbnail_path, suffix = self.get_thumbnail_file(
                    source_file.path, thumbnail_key
                )
                if thumbnail_path:
                    file_name += suffix
                    file = open(thumbnail_path, "rb")
                else:
                    file = source_file.file
            else:
                file = source_file.file

            response = FileResponse(file)
            disposition_type = "attachment" if download else "inline"
            response["Content-Disposition"] = (
                f'{disposition_type}; filename="{file_name}"'
            )
            return response

        except Exception as e:
            return Response(
                {"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class FileDetailView(GenericAPIView):
    """
    API view to get file metadata without serving the actual file.

    Authentication can be provided via:
    1. Authorization header (JWT token)
    2. 'token' query parameter (JWT token)
    """

    permission_classes = [IsAuthenticated]
    serializer_class = PostFileSerializer
    queryset = PostFileModel.objects.all()

    @extend_schema(
        parameters=[
            OpenApiParameter(
                name="token",
                description="JWT token for authentication (alternative to Authorization header)",
                required=False,
                type=str,
            )
        ],
        responses={
            200: PostFileSerializer,
            401: ErrorResponseSerializer,
            404: ErrorResponseSerializer,
            500: ErrorResponseSerializer,
        },
    )
    def get(self, request, file_hash):
        """Return file metadata."""
        try:
            obj_file = PostFileModel.objects.filter(hash_blake3=file_hash).first()
            if not obj_file:
                return Response(
                    {"error": "File not found"}, status=status.HTTP_404_NOT_FOUND
                )

            serializer = self.get_serializer(obj_file)
            return Response(serializer.data)

        except Exception as e:
            return Response(
                {"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )