from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from .models import Link, ImageCollection, Image, FileUpload
from .serializers import LinkSerializer, ImageCollectionSerializer, ImageSerializer, ImageDescriptionSerializer
from .storage import R2Storage
from .file_views import _save_uploaded_file, FileSaveError
import uuid
import logging
import os
from django.conf import settings


def _delete_image_file(image):
    """Remove the FileUpload backing an Image (disk file + DB record).

    The Image→FileUpload link is SET_NULL, so deleting the FileUpload never
    cascades to the Image — callers delete the Image record themselves.
    """
    if not image.file:
        return
    try:
        path = image.file.file_path
        if os.path.exists(path):
            os.remove(path)
        # Also remove the generated thumbnail, if any
        thumb = image.file.thumb_path
        if os.path.exists(thumb):
            os.remove(thumb)
    except OSError:
        logger.warning("Failed to remove file on disk for %s", image.file.pk, exc_info=True)
    image.file.delete()


logger = logging.getLogger(__name__)


class StandardResultsSetPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    max_page_size = 100


class LinkViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = LinkSerializer
    pagination_class = StandardResultsSetPagination

    def get_queryset(self):
        return Link.objects.prefetch_related('tags').order_by('-created_at')

    @action(detail=False, methods=['get'], url_path='most-visited')
    def most_visited(self, request):
        """Return links sorted by click_count descending."""
        queryset = Link.objects.prefetch_related('tags').filter(click_count__gt=0).order_by('-click_count')
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

class ImageCollectionViewSet(viewsets.ModelViewSet):
    queryset = ImageCollection.objects.all()
    serializer_class = ImageCollectionSerializer

    def create(self, request, *args, **kwargs):
        """Create a new collection"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            {
                'status': 'success',
                'message': 'Collection created successfully',
                'data': serializer.data
            },
            status=status.HTTP_201_CREATED,
            headers=headers
        )

    def perform_destroy(self, instance):
        """Delete the collection AND every backing file (disk + FileUpload).

        Django's CASCADE on Image only removes the Image rows; the linked
        FileUpload records (SET_NULL) and their files on disk would otherwise
        be orphaned. Clean them up explicitly first.
        """
        for image in instance.images.select_related('file').all():
            # Legacy R2 objects, if any
            if image.file_key:
                try:
                    R2Storage().delete_file(image.file_key)
                except Exception as e:
                    logger.error(f"Failed to delete from storage: {e}")
            _delete_image_file(image)
        instance.delete()

    @action(detail=True, methods=['post'])
    def upload_images(self, request, pk=None):
        """Upload images to a collection (files backend — same storage as FileUpload)."""
        collection = self.get_object()
        files = request.FILES.getlist('file')
        descriptions = request.data.getlist('descriptions', [])  # Get descriptions list

        logger.debug(f"Processing upload request for collection {collection.id}")
        logger.debug(f"Number of files: {len(files)}")

        uploaded_images = []
        for idx, file in enumerate(files):
            try:
                logger.debug(f"Processing file: {file.name}")

                # Get description for this file if available
                description = descriptions[idx] if idx < len(descriptions) else None

                # Validate file
                if not hasattr(file, 'read'):
                    raise ValueError("Invalid file object - missing read method")

                if not (file.content_type or '').startswith('image/'):
                    raise ValueError("Invalid file type. Only images are allowed.")

                # Persist to the files backend (FILE_UPLOADS_FOLDER + FileUpload record)
                try:
                    upload = _save_uploaded_file(file)
                except FileSaveError as exc:
                    logger.error(f"Storage upload failed: {exc}", exc_info=True)
                    raise ValueError(f"Storage upload failed: {exc}")

                # Create image record linked to the FileUpload
                image = Image.objects.create(
                    collection=collection,
                    title=file.name,
                    description=description,
                    file=upload,
                    file_key='',  # legacy R2 key no longer used for new uploads
                    content_type=upload.mime_type,
                    size=upload.size,
                )

                logger.debug(f"Created image record: {image.id}")
                uploaded_images.append(ImageSerializer(image).data)

            except Exception as e:
                logger.error(f"Upload failed for {file.name}", exc_info=True)
                return Response({
                    'status': 'error',
                    'message': str(e)
                }, status=status.HTTP_400_BAD_REQUEST)

        return Response({
            'status': 'success',
            'message': f'Successfully uploaded {len(uploaded_images)} images',
            'data': uploaded_images
        }, status=status.HTTP_201_CREATED)

    @action(detail=True, methods=['delete'])
    def delete_image(self, request, pk=None):
        """Delete an image from a collection"""
        collection = self.get_object()
        image_id = request.data.get('image_id')

        try:
            image = collection.images.get(id=image_id)

            # Delete legacy R2 object if this image predates the files backend
            if image.file_key:
                try:
                    R2Storage().delete_file(image.file_key)
                except Exception as e:
                    logger.error(f"Failed to delete from storage: {e}")

            # Delete the FileUpload (disk + record) when present
            _delete_image_file(image)

            # Delete from database
            image.delete()

            return Response({
                'status': 'success',
                'message': 'Image deleted successfully'
            })

        except Image.DoesNotExist:
            return Response({
                'status': 'error',
                'message': 'Image not found'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'status': 'error',
                'message': str(e)
            }, status=status.HTTP_400_BAD_REQUEST)

class ImageViewSet(viewsets.ModelViewSet):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer

    @action(detail=True, methods=['patch'], url_path='update-description')
    def update_description(self, request, pk=None):
        """Update the description of an image"""
        image = self.get_object()
        serializer = ImageDescriptionSerializer(image, data=request.data, partial=True)
        
        if serializer.is_valid():
            serializer.save()
            return Response({
                'status': 'success',
                'message': 'Description updated successfully',
                'data': serializer.data
            })
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def perform_destroy(self, instance):
        """Delete image record + backing file storage when deleting record"""
        # Delete legacy R2 object if this image predates the files backend
        if instance.file_key:
            try:
                R2Storage().delete_file(instance.file_key)
            except Exception as e:
                logger.error(f"Failed to delete from storage: {e}")
        _delete_image_file(instance)
        instance.delete()

class MusicViewSet(viewsets.ViewSet):
    def list(self, request):
        static_music = [
            {'title': 'Purple Planet', 'src': '/static/music/Purple-Planet.mp3'},
            {'title': 'Just Kidding', 'src': '/static/music/mixkit-just-kidding.mp3'},
            {'title': 'Thomas', 'src': '/static/music/Thomas-the-Tank-Engine.mp3'}
        ]
        
        data_music_dir = os.path.join(settings.BASE_DIR, 'data', 'music')
        data_music = []
        for file in os.listdir(data_music_dir):
            if file.endswith('.mp3'):
                title = os.path.splitext(file)[0].replace('-', ' ').replace('_', ' ')
                data_music.append({'title': title, 'src': f'/music/{file}'})
        
        return Response(static_music + data_music)