"""
API views для работы с LiveKit.
"""
import json
import logging
import uuid
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from django.conf import settings

from .livekit_service import LiveKitService
from .models import VideoRoom
from apps.board.models import Board
from apps.schedule.models import Lesson
from apps.users.utils import format_datetime_for_user

logger = logging.getLogger(__name__)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def create_livekit_room(request):
    """
    Получение данных LiveKit комнаты для занятия.
    Комната создаётся автоматически при создании урока.
    
    POST /api/video/livekit/create-room/
    Body: {
        "lesson_id": 123
    }
    
    Returns:
        {
            "room_name": "uuid",
            "access_token": "token",
            "video_room_id": 1,
            "server_url": "ws://livekit:7880",
            "ice_servers": [...]
        }
    """
    lesson_id = request.data.get('lesson_id')
    
    if not lesson_id:
        return Response(
            {'error': 'lesson_id обязателен'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    try:
        lesson = Lesson.objects.get(id=lesson_id)
    except Lesson.DoesNotExist:
        return Response(
            {'error': 'Занятие не найдено'},
            status=status.HTTP_404_NOT_FOUND
        )
    
    # Проверка прав доступа
    user = request.user
    if user != lesson.mentor and (not hasattr(user, 'client_profile') or user.client_profile != lesson.client):
        return Response(
            {'error': 'Нет доступа к этому занятию'},
            status=status.HTTP_403_FORBIDDEN
        )
    
    # Проверка времени подключения
    from django.utils import timezone
    from datetime import timedelta
    now = timezone.now()
    
    # Можно подключиться за 10 минут до начала урока
    allowed_start_time = lesson.start_time - timedelta(minutes=10)
    if now < allowed_start_time:
        minutes_until_allowed = int((allowed_start_time - now).total_seconds() / 60)
        return Response(
            {'error': f'Подключение к уроку будет доступно за 10 минут до начала ({allowed_start_time.strftime("%H:%M")}). Осталось {minutes_until_allowed} минут.'},
            status=status.HTTP_403_FORBIDDEN
        )
    
    # Нельзя подключиться позже 15 минут после окончания урока
    if lesson.end_time:
        # Используем фактическое время завершения, если оно есть, иначе запланированное
        actual_end_time = lesson.completed_at if (lesson.status == 'completed' and lesson.completed_at) else lesson.end_time
        allowed_end_time = actual_end_time + timedelta(minutes=15)
        
        if now > allowed_end_time:
            return Response(
                {'error': 'Доступ к видеокомнате закрыт. Прошло более 15 минут после завершения урока.'},
                status=status.HTTP_403_FORBIDDEN
            )
    
    # Если LiveKit комната не создана — создаём «на лету» (fallback при сбое при создании урока)
    if not lesson.livekit_room_name:
        try:
            try:
                existing = VideoRoom.objects.get(lesson=lesson)
                room_name = str(existing.room_id)
            except VideoRoom.DoesNotExist:
                room_name = LiveKitService.generate_room_name()
                client_user = lesson.client.user if hasattr(lesson.client, 'user') else lesson.client
                VideoRoom.objects.create(
                    lesson=lesson,
                    mentor=lesson.mentor,
                    client=client_user,
                    room_id=room_name,
                    is_recording=True,
                    max_participants=10 if lesson.group else 2,
                )
            mentor_token = LiveKitService.generate_access_token(
                room_name=room_name,
                participant_name=lesson.mentor.get_full_name(),
                participant_identity=str(lesson.mentor.pk),
                is_admin=True,
                expires_in_minutes=1440,
            )
            lesson.livekit_room_name = room_name
            lesson.livekit_access_token = mentor_token
            lesson.save(update_fields=['livekit_room_name', 'livekit_access_token'])
            logger.info(f'LiveKit room created on-demand for lesson {lesson.id}')
        except Exception:
            logger.exception(f'Failed to create LiveKit room for lesson {lesson.id}')
            return Response(
                {'error': 'LiveKit комната не создана для этого урока. Обратитесь к администратору.'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    room_name = lesson.livekit_room_name
    
    # Получаем или создаем VideoRoom запись
    try:
        video_room = VideoRoom.objects.get(lesson=lesson)
    except VideoRoom.DoesNotExist:
        client_user = lesson.client.user if hasattr(lesson.client, 'user') else lesson.client
        video_room = VideoRoom.objects.create(
            lesson=lesson,
            mentor=lesson.mentor,
            client=client_user,
            room_id=room_name,
            is_recording=True,
            max_participants=10 if lesson.group else 2
        )
    
    # Определяем роль пользователя
    is_admin = user == lesson.mentor

    # Получаем или создаём доску для пары ментор–студент (одна доска на пару, в metadata токена)
    mentor_id = lesson.mentor_id
    client_obj = lesson.client
    student_user = client_obj.user if hasattr(client_obj, 'user') else client_obj
    student_id = getattr(student_user, 'id', getattr(student_user, 'pk', None))
    token_metadata = None
    if mentor_id and student_id:
        board, created = Board.objects.get_or_create(
            mentor_id=mentor_id,
            student_id=student_id,
            defaults={
                'title': 'Доска для совместной работы',
                'description': 'Интерактивная доска для занятия',
                'access_type': 'mentor_student',
                'owner': lesson.mentor,
            }
        )
        if created:
            board.participants.add(lesson.mentor, student_user)
        token_metadata = json.dumps({
            'board_id': str(board.board_id),
            'is_mentor': is_admin,
        })

    participant_identity = str(user.pk) if hasattr(user, 'pk') and user.pk else str(user.id)
    participant_name = user.get_full_name() or user.email or f"User {participant_identity}"

    access_token = LiveKitService.generate_access_token(
        room_name=room_name,
        participant_name=participant_name,
        participant_identity=participant_identity,
        is_admin=is_admin,
        expires_in_minutes=180,  # 3 часа
        metadata=token_metadata,
    )
    
    logger.info(f'LiveKit token generated for user {user.id} (identity={participant_identity}) in room {room_name}')
    
    # Получаем ICE серверы
    ice_servers = LiveKitService.get_ice_servers()
    server_url = LiveKitService.get_server_url(request=request)

    return Response({
        'room_name': str(room_name),
        'access_token': access_token,
        'server_url': server_url,
        'ice_servers': ice_servers,
        'video_room_id': video_room.id,
        'is_admin': is_admin,
        'lesson': {
            'id': lesson.id,
            'title': lesson.title,
            'start_time': format_datetime_for_user(lesson.start_time, request.user.timezone) if lesson.start_time else None,
            'end_time': format_datetime_for_user(lesson.end_time, request.user.timezone) if lesson.end_time else None,
        }
    })


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_livekit_config(request):
    """
    Получение конфигурации LiveKit для фронтенда.
    
    GET /api/video/livekit/config/
    
    Returns:
        {
            "server_url": "ws://livekit:7880",
            "ice_servers": [...]
        }
    """
    return Response({
        'server_url': LiveKitService.get_server_url(request=request),
        'ice_servers': LiveKitService.get_ice_servers(),
    })


@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def delete_livekit_room_by_lesson(request, lesson_id):
    """
    Удаление LiveKit видеокомнаты по ID занятия.
    
    DELETE /api/video/livekit/rooms/lesson/{lesson_id}/
    
    Проверяет, что прошло минимум 10 минут после окончания занятия.
    Только ментор может удалять видеокомнату.
    """
    from django.utils import timezone
    from datetime import timedelta
    
    try:
        lesson = Lesson.objects.get(id=lesson_id)
    except Lesson.DoesNotExist:
        return Response(
            {'error': 'Занятие не найдено'},
            status=status.HTTP_404_NOT_FOUND
        )
    
    # Проверка прав доступа - только ментор может удалять
    user = request.user
    if user != lesson.mentor:
        return Response(
            {'error': 'Только ментор может удалять видеокомнату'},
            status=status.HTTP_403_FORBIDDEN
        )
    
    # Проверка времени - можно удалять только через 10 минут после фактического окончания
    if lesson.end_time:
        now = timezone.now()
        
        # Используем фактическое время завершения, если оно есть, иначе запланированное
        actual_end_time = lesson.completed_at if (lesson.status == 'completed' and lesson.completed_at) else lesson.end_time
        allowed_delete_time = actual_end_time + timedelta(minutes=10)
        
        if now < allowed_delete_time:
            minutes_remaining = int((allowed_delete_time - now).total_seconds() / 60)
            return Response(
                {
                    'error': f'Видеокомнату можно удалить только через 10 минут после окончания занятия. Осталось {minutes_remaining} минут.'
                },
                status=status.HTTP_400_BAD_REQUEST
            )
    else:
        return Response(
            {'error': 'Время окончания занятия не указано'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    # Проверяем, есть ли VideoRoom для этого занятия
    try:
        video_room = VideoRoom.objects.get(lesson=lesson)
        
        # Удаляем комнату из SFU сервера (если используется)
        from .services import get_sfu_client, SFUClientError
        sfu_client = get_sfu_client()
        try:
            sfu_client.delete_room(str(video_room.room_id))
        except SFUClientError as e:
            # Логируем ошибку, но продолжаем удаление из Django
            import logging
            logger = logging.getLogger(__name__)
            logger.warning(f'Не удалось удалить комнату из SFU сервера: {e}')
        
        # Удаляем комнату из базы данных
        video_room.delete()
        
        return Response(
            {'message': 'Видеокомната успешно удалена'},
            status=status.HTTP_200_OK
        )
    except VideoRoom.DoesNotExist:
        return Response(
            {'error': 'Видеокомната для этого занятия не найдена'},
            status=status.HTTP_404_NOT_FOUND
        )


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def participant_connected(request):
    """
    Отметить подключение участника к видеокомнате (для метрик).
    Вызывается фронтендом при успешном подключении к LiveKit комнате.
    
    POST /api/video/livekit/participant-connected/
    Body: { "room_name": "uuid", "lesson_id": 123 }  — lesson_id опционален, резерв при 404 по room_name
    """
    room_name = request.data.get('room_name')
    lesson_id = request.data.get('lesson_id')
    
    if not room_name and not lesson_id:
        return Response(
            {'error': 'Укажите room_name или lesson_id'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    video_room = None
    if room_name:
        try:
            import uuid as uuid_module
            room_uuid = uuid_module.UUID(str(room_name).strip())
            video_room = VideoRoom.objects.get(room_id=room_uuid)
        except (ValueError, VideoRoom.DoesNotExist):
            pass
    if not video_room and lesson_id:
        try:
            video_room = VideoRoom.objects.get(lesson_id=lesson_id)
        except VideoRoom.DoesNotExist:
            pass
    
    if not video_room:
        logger.warning(
            'participant_connected: VideoRoom not found (room_name=%s, lesson_id=%s, user=%s)',
            room_name, lesson_id, getattr(request.user, 'pk', request.user)
        )
        return Response(
            {'error': 'Видеокомната не найдена'},
            status=status.HTTP_404_NOT_FOUND
        )
    
    user = request.user
    client_user = video_room.client.user if hasattr(video_room.client, 'user') else video_room.client
    is_mentor = user.pk == video_room.mentor_id
    client_pk = getattr(client_user, 'pk', None) or getattr(client_user, 'id', None)
    is_client = client_pk is not None and user.pk == client_pk
    if not is_mentor and not is_client:
        return Response(
            {'error': 'Нет доступа к этой видеокомнате'},
            status=status.HTTP_403_FORBIDDEN
        )
    
    from .models import VideoParticipant
    participant, _ = VideoParticipant.objects.get_or_create(
        room=video_room,
        user=user,
        defaults={
            'is_connected': True,
            'is_audio_enabled': True,
            'is_video_enabled': True,
        }
    )
    if not participant.is_connected:
        participant.is_connected = True
        participant.save(update_fields=['is_connected'])
    
    video_room.mark_participant_joined(user)
    logger.info(
        'participant_connected: marked %s for lesson %s (room %s)',
        'mentor' if is_mentor else 'client',
        video_room.lesson_id,
        video_room.room_id,
    )
    return Response({'success': True}, status=status.HTTP_200_OK)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def update_livekit_participant_media_state(request):
    """
    Обновление состояния медиа (камера/микрофон) участника LiveKit комнаты.
    
    POST /api/video/livekit/update-media-state/
    Body: {
        "room_name": "uuid",
        "audio_enabled": true,
        "video_enabled": false
    }
    """
    room_name = request.data.get('room_name')
    audio_enabled = request.data.get('audio_enabled')
    video_enabled = request.data.get('video_enabled')
    
    if not room_name:
        return Response(
            {'error': 'room_name обязателен'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    if audio_enabled is None and video_enabled is None:
        return Response(
            {'error': 'Необходимо указать хотя бы одно из: audio_enabled, video_enabled'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    try:
        # Находим комнату по room_name (это строка room_id)
        try:
            import uuid
            room_uuid = uuid.UUID(str(room_name))
            video_room = VideoRoom.objects.get(room_id=room_uuid)
        except (ValueError, VideoRoom.DoesNotExist):
            return Response(
                {'error': 'Видеокомната не найдена'},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Проверяем права доступа
        user = request.user
        client_user = video_room.client.user if hasattr(video_room.client, 'user') else video_room.client
        if user != video_room.mentor and user != client_user:
            return Response(
                {'error': 'Нет доступа к этой видеокомнате'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Находим или создаем участника
        from .models import VideoParticipant
        participant, created = VideoParticipant.objects.get_or_create(
            room=video_room,
            user=user,
            defaults={
                'is_connected': True,
                'is_audio_enabled': audio_enabled if audio_enabled is not None else True,
                'is_video_enabled': video_enabled if video_enabled is not None else True,
            }
        )
        # Фиксируем подключение ментора/студента для метрик
        video_room.mark_participant_joined(user)
        
        if not created:
            # Обновляем существующего участника
            if audio_enabled is not None:
                participant.is_audio_enabled = audio_enabled
            if video_enabled is not None:
                participant.is_video_enabled = video_enabled
            if not participant.is_connected:
                participant.is_connected = True
            participant.save()
        
        return Response({
            'success': True,
            'participant_id': participant.id,
            'audio_enabled': participant.is_audio_enabled,
            'video_enabled': participant.is_video_enabled,
        }, status=status.HTTP_200_OK)
        
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        logger.error(f'Ошибка обновления медиа-состояния участника: {str(e)}')
        return Response(
            {'error': f'Ошибка обновления медиа-состояния: {str(e)}'},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

