"""
音乐模块视图 - App端
"""
from django.db import transaction
from django.http import StreamingHttpResponse
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from drf_spectacular.utils import extend_schema

from utils.response import success, error
from utils.exceptions import ErrorCode
from apps.admins.authentication import AppJWTAuthentication
from apps.users.models import PointsRecord
from .models import Track
from .serializers import TrackSerializer, GenerateMusicSerializer
from .utils import ensure_default_tracks

GENERATE_COST = 100


@extend_schema(tags=['音乐'])
class MusicViewSet(viewsets.ViewSet):
    """音乐视图集（App端）"""

    authentication_classes = [AppJWTAuthentication]
    permission_classes = [IsAuthenticated]

    @action(detail=False, methods=['get'], url_path='playlist')
    def playlist(self, request):
        """
        获取播放列表
        GET /api/v1/music/playlist/
        自动初始化默认曲目，返回用户歌曲（时间倒序）+ 默认歌曲（末尾）
        """
        ensure_default_tracks(request.user)

        user_tracks = Track.objects.filter(
            user=request.user, is_default=False
        ).order_by('-created_at')
        default_tracks = Track.objects.filter(
            user=request.user, is_default=True
        ).order_by('created_at')

        playlist_data = (
            TrackSerializer(user_tracks, many=True).data
            + TrackSerializer(default_tracks, many=True).data
        )
        return success(data={'playlist': playlist_data})

    def destroy(self, request, pk=None):
        """
        删除音乐
        DELETE /api/v1/music/{id}/
        """
        try:
            track = Track.objects.get(id=pk, user=request.user)
        except Track.DoesNotExist:
            return error(code=ErrorCode.TRACK_NOT_FOUND, message='曲目不存在')

        if track.is_default:
            return error(
                code=ErrorCode.MUSIC_DEFAULT_UNDELETABLE,
                message='默认曲目不可删除'
            )

        track.delete()
        return success(message='删除成功')

    @action(detail=True, methods=['post'])
    def favorite(self, request, pk=None):
        """
        收藏/取消收藏
        POST /api/v1/music/{id}/favorite/
        """
        try:
            track = Track.objects.get(id=pk, user=request.user)
        except Track.DoesNotExist:
            return error(code=ErrorCode.TRACK_NOT_FOUND, message='曲目不存在')

        track.is_favorite = not track.is_favorite
        track.save(update_fields=['is_favorite'])

        return success(
            data={'is_favorite': track.is_favorite},
            message='已收藏' if track.is_favorite else '已取消收藏'
        )

    @action(detail=False, methods=['post'], url_path='generate')
    def generate(self, request):
        """
        生成音乐 (SSE 流式)
        POST /api/v1/music/generate/
        消耗 100 积分，先扣后退（失败退还）
        """
        serializer = GenerateMusicSerializer(data=request.data)
        if not serializer.is_valid():
            return error(message=str(serializer.errors))

        text = serializer.validated_data.get('text', '')
        mood = serializer.validated_data.get('mood', 'custom')
        user = request.user

        # 积分校验
        if user.points < GENERATE_COST:
            return error(
                code=ErrorCode.POINTS_NOT_ENOUGH,
                message=f'积分不足，需要 {GENERATE_COST} 积分，当前 {user.points} 积分'
            )

        # 原子操作：扣积分 + 创建 Track 占位
        with transaction.atomic():
            user.points -= GENERATE_COST
            user.save(update_fields=['points'])

            PointsRecord.objects.create(
                user=user,
                amount=-GENERATE_COST,
                type='generate_music',
                description='生成音乐',
            )

            track = Track.objects.create(
                user=user,
                title='生成中...',
                mood=mood,
                prompt=text,
                generation_status='generating',
            )

        from .services.music_generation_service import generate_music_stream

        response = StreamingHttpResponse(
            generate_music_stream(user, track, text, mood),
            content_type='text/event-stream',
        )
        response['Cache-Control'] = 'no-cache'
        response['X-Accel-Buffering'] = 'no'
        return response
