"""
Views для уведомлений.
"""
from rest_framework import viewsets, status, generics
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.conf import settings
from .models import Notification, NotificationPreference, ParentChildNotificationSettings, PushSubscription
from .serializers import (
    NotificationSerializer, 
    NotificationPreferenceSerializer,
    ParentChildNotificationSettingsSerializer,
    PushSubscriptionSerializer
)
from .services import TelegramLinkService
import asyncio


class NotificationViewSet(viewsets.ReadOnlyModelViewSet):
    """ViewSet для уведомлений (только чтение)."""
    
    queryset = Notification.objects.all()
    serializer_class = NotificationSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """Только in_app уведомления текущего пользователя."""
        queryset = Notification.objects.filter(
            recipient=self.request.user,
            channel='in_app'  # Показываем только in_app уведомления
        )
        
        # Оптимизация: для списка используем only() для ограничения полей
        # Не используем select_related для recipient, так как он не нужен в сериализаторе
        if self.action == 'list':
            return queryset.only(
                'id', 'notification_type', 'channel', 'priority',
                'title', 'message', 'data', 'action_url',
                'is_read', 'read_at', 'is_sent', 'created_at'
            ).order_by('is_read', '-created_at')  # сначала непрочитанные, затем по дате
        
        # Для детального просмотра можно использовать select_related, если нужно
        return queryset.order_by('is_read', '-created_at')
    
    @action(detail=False, methods=['get'])
    def unread(self, request):
        """Получить непрочитанные уведомления."""
        queryset = self.get_queryset().filter(is_read=False)
        # Оптимизация: используем len() вместо count() для уже загруженного queryset
        serializer = self.get_serializer(queryset, many=True)
        return Response({
            'success': True,
            'data': serializer.data,
            'count': len(serializer.data)  # Используем len() вместо count() для оптимизации
        })
    
    @action(detail=True, methods=['post'])
    def mark_as_read(self, request, pk=None):
        """Отметить как прочитанное."""
        notification = self.get_object()
        notification.mark_as_read()
        
        return Response({
            'success': True,
            'message': 'Уведомление отмечено как прочитанное'
        })
    
    @action(detail=False, methods=['post'])
    def mark_all_as_read(self, request):
        """Отметить все как прочитанные."""
        from django.core.cache import cache
        count = self.get_queryset().filter(is_read=False).update(is_read=True)
        # Очищаем кеш дашборда для обновления счетчика непрочитанных уведомлений
        user_id = request.user.id
        cache.delete(f'mentor_dashboard_{user_id}')
        cache.delete(f'client_dashboard_{user_id}')
        cache.delete(f'parent_dashboard_{user_id}')
        
        return Response({
            'success': True,
            'message': f'Отмечено {count} уведомлений'
        })


class NotificationPreferenceViewSet(viewsets.ModelViewSet):
    """ViewSet для настроек уведомлений."""
    
    queryset = NotificationPreference.objects.all()
    serializer_class = NotificationPreferenceSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """Только настройки текущего пользователя."""
        queryset = NotificationPreference.objects.filter(user=self.request.user).select_related('user')
        
        # Оптимизация: для списка используем only() для ограничения полей
        if self.action == 'list':
            queryset = queryset.only(
                'id', 'user_id', 'enabled', 'email_enabled', 'telegram_enabled',
                'in_app_enabled', 'type_preferences', 'quiet_hours_enabled',
                'quiet_hours_start', 'quiet_hours_end', 'created_at', 'updated_at'
            )
        
        return queryset
    
    @action(detail=False, methods=['get', 'put', 'patch'])
    def me(self, request):
        """Получить или обновить свои настройки."""
        try:
            preferences = request.user.notification_preferences
        except:
            # Создаем если нет
            from .services import create_notification_preferences
            create_notification_preferences(request.user)
            preferences = request.user.notification_preferences
        
        if request.method == 'GET':
            serializer = self.get_serializer(preferences)
            return Response({
                'success': True,
                'data': serializer.data
            })
        
        else:  # PUT, PATCH
            serializer = self.get_serializer(
                preferences,
                data=request.data,
                partial=request.method == 'PATCH'
            )
            serializer.is_valid(raise_exception=True)
            serializer.save()
            
            return Response({
                'success': True,
                'message': 'Настройки обновлены',
                'data': serializer.data
            })
    
    @action(detail=False, methods=['get'], url_path='telegram/bot-info')
    def get_telegram_bot_info(self, request):
        """
        Получение информации о Telegram боте (username, ссылка).
        
        GET /api/notifications/preferences/telegram/bot-info/
        """
        try:
            import logging
            from telegram import Bot
            from telegram.error import TelegramError
            
            logger = logging.getLogger(__name__)
            
            if not getattr(settings, 'TELEGRAM_BOT_TOKEN', None) or not settings.TELEGRAM_BOT_TOKEN.strip():
                return Response({
                    'success': False,
                    'error': 'TELEGRAM_BOT_TOKEN не настроен'
                }, status=status.HTTP_200_OK)
            
            async def get_bot_info():
                bot = Bot(token=settings.TELEGRAM_BOT_TOKEN)
                try:
                    me = await bot.get_me()
                    return {
                        'username': me.username,
                        'first_name': me.first_name,
                        'id': me.id,
                        'link': f'https://t.me/{me.username}'
                    }
                finally:
                    # Игнорируем ошибки при закрытии (rate limiting)
                    try:
                        await bot.close()
                    except (TelegramError, Exception) as close_error:
                        logger.warning(f'Ошибка при закрытии бота (игнорируется): {close_error}')
            
            bot_info = asyncio.run(get_bot_info())
            return Response({
                'success': True,
                **bot_info
            })
        except Exception as e:
            import logging
            logger = logging.getLogger(__name__)
            logger.error(f'Ошибка при получении информации о Telegram боте: {str(e)}', exc_info=True)
            return Response({
                'success': False,
                'error': f'Не удалось получить информацию о боте: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'], url_path='telegram/generate-code')
    def generate_telegram_code(self, request):
        """
        Генерация кода для связывания Telegram аккаунта.
        
        POST /api/notifications/preferences/telegram/generate-code/
        """
        code = TelegramLinkService.generate_link_code(request.user.id)
        
        return Response({
            'success': True,
            'code': code,
            'message': 'Код сгенерирован. Действителен 15 минут.',
            'instructions': (
                f'1. Откройте Telegram бота\n'
                f'2. Отправьте команду: /link {code}\n'
                f'3. Ваш аккаунт будет связан'
            )
        })
    
    @action(detail=False, methods=['post'], url_path='telegram/unlink')
    def unlink_telegram(self, request):
        """
        Отвязка Telegram аккаунта.
        
        POST /api/notifications/preferences/telegram/unlink/
        """
        user = request.user
        
        if not user.telegram_id:
            return Response({
                'success': False,
                'error': 'Telegram аккаунт не привязан'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        user.telegram_id = None
        user.telegram_username = ''
        user.save(update_fields=['telegram_id', 'telegram_username'])
        
        # Выключаем Telegram уведомления
        try:
            preferences = user.notification_preferences
            preferences.telegram_enabled = False
            preferences.save(update_fields=['telegram_enabled'])
        except:
            pass
        
        return Response({
            'success': True,
            'message': 'Telegram аккаунт успешно отвязан'
        })
    
    @action(detail=False, methods=['get'], url_path='telegram/status')
    def telegram_status(self, request):
        """
        Проверка статуса связывания Telegram.
        
        GET /api/notifications/preferences/telegram/status/
        """
        user = request.user
        
        return Response({
            'success': True,
            'linked': bool(user.telegram_id),
            'telegram_id': user.telegram_id,
            'telegram_username': user.telegram_username,
            'notifications_enabled': (
                user.notification_preferences.telegram_enabled
                if hasattr(user, 'notification_preferences')
                else False
            )
        })


class ParentChildNotificationSettingsViewSet(viewsets.ModelViewSet):
    """ViewSet для настроек уведомлений родителя для детей."""
    
    serializer_class = ParentChildNotificationSettingsSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """Только настройки текущего родителя."""
        user = self.request.user
        if user.role != 'parent':
            return ParentChildNotificationSettings.objects.none()
        
        try:
            parent = user.parent_profile
        except:
            return ParentChildNotificationSettings.objects.none()
        
        queryset = ParentChildNotificationSettings.objects.filter(
            parent=parent
        ).select_related(
            'parent', 'parent__user',
            'child', 'child__user'
        )
        
        # Фильтр по ребенку
        child_id = self.request.query_params.get('child_id')
        if child_id:
            try:
                from apps.users.models import Client
                child = Client.objects.get(user_id=child_id)
                # Проверяем, что ребенок связан с родителем
                if child in parent.children.all():
                    queryset = queryset.filter(child=child)
                else:
                    queryset = ParentChildNotificationSettings.objects.none()
            except Client.DoesNotExist:
                queryset = ParentChildNotificationSettings.objects.none()
            except Exception:
                queryset = ParentChildNotificationSettings.objects.none()
        
        return queryset
    
    def perform_create(self, serializer):
        """Создание настроек с автоматическим определением родителя."""
        user = self.request.user
        if user.role != 'parent':
            from rest_framework.exceptions import PermissionDenied
            raise PermissionDenied("Только родители могут создавать настройки уведомлений")
        
        parent = user.parent_profile
        serializer.save(parent=parent)
    
    @action(detail=False, methods=['get', 'post', 'put', 'patch'], url_path='for_child')
    def for_child(self, request):
        """
        Получить или обновить настройки уведомлений для конкретного ребенка.
        
        GET /api/notifications/parent-child-settings/for_child/?child_id=17
        POST/PUT/PATCH /api/notifications/parent-child-settings/for_child/?child_id=17
        Body: {
            "enabled": true,
            "type_settings": {
                "lesson_created": true,
                "homework_assigned": false,
                ...
            }
        }
        """
        user = request.user
        if user.role != 'parent':
            return Response(
                {'error': 'Только родители могут управлять настройками уведомлений'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        child_id = request.query_params.get('child_id')
        if not child_id:
            return Response(
                {'error': 'Параметр child_id обязателен'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            from apps.users.models import Client, Parent
            parent = user.parent_profile
            if not parent:
                return Response(
                    {'error': 'Профиль родителя не найден'},
                    status=status.HTTP_404_NOT_FOUND
                )
            
            # Получаем ребенка по user_id и проверяем, что он связан с родителем
            try:
                child = Client.objects.get(user_id=child_id)
            except Client.DoesNotExist:
                return Response(
                    {'error': 'Ребенок не найден'},
                    status=status.HTTP_404_NOT_FOUND
                )
            
            # Проверяем, что ребенок связан с этим родителем
            if child not in parent.children.all():
                return Response(
                    {'error': 'Ребенок не связан с этим родителем'},
                    status=status.HTTP_403_FORBIDDEN
                )
        except Exception as e:
            import logging
            logger = logging.getLogger(__name__)
            logger.error(f'Ошибка в for_child: {str(e)}', exc_info=True)
            return Response(
                {'error': f'Ошибка при получении данных: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
        
        # Получаем или создаем настройки
        settings, created = ParentChildNotificationSettings.objects.get_or_create(
            parent=parent,
            child=child,
            defaults={'enabled': True, 'type_settings': {}}
        )
        
        if request.method == 'GET':
            serializer = self.get_serializer(settings)
            return Response(serializer.data)
        
        # Обновление настроек
        serializer = self.get_serializer(settings, data=request.data, partial=request.method == 'PATCH')
        serializer.is_valid(raise_exception=True)
        serializer.save()
        
        return Response(serializer.data)


class PushSubscriptionView(generics.GenericAPIView):
    """
    API endpoint для сохранения Push Notification subscription.
    
    POST /api/notifications/push-subscription/
    """
    serializer_class = PushSubscriptionSerializer
    permission_classes = [IsAuthenticated]
    
    def post(self, request, *args, **kwargs):
        """Сохранение или обновление Push subscription."""
        user = request.user
        subscription_data = request.data.get('subscription_data')
        user_agent = request.META.get('HTTP_USER_AGENT', '')
        
        if not subscription_data:
            return Response({
                'success': False,
                'error': 'subscription_data обязателен'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        # Проверяем, есть ли уже такая subscription
        # Используем endpoint из subscription_data как уникальный идентификатор
        endpoint = subscription_data.get('endpoint')
        if endpoint:
            existing = PushSubscription.objects.filter(
                user=user,
                subscription_data__endpoint=endpoint
            ).first()
            
            if existing:
                # Обновляем существующую
                existing.subscription_data = subscription_data
                existing.user_agent = user_agent
                existing.is_active = True
                existing.save()
                
                return Response({
                    'success': True,
                    'message': 'Push subscription обновлена',
                    'subscription_id': existing.id
                }, status=status.HTTP_200_OK)
        
        # Создаем новую subscription
        subscription = PushSubscription.objects.create(
            user=user,
            subscription_data=subscription_data,
            user_agent=user_agent
        )
        
        return Response({
            'success': True,
            'message': 'Push subscription сохранена',
            'subscription_id': subscription.id
        }, status=status.HTTP_201_CREATED)
    
    def delete(self, request, *args, **kwargs):
        """Удаление Push subscription."""
        user = request.user
        endpoint = request.data.get('endpoint')
        
        if not endpoint:
            return Response({
                'success': False,
                'error': 'endpoint обязателен'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        # Деактивируем subscription
        count = PushSubscription.objects.filter(
            user=user,
            subscription_data__endpoint=endpoint
        ).update(is_active=False)
        
        return Response({
            'success': True,
            'message': f'Деактивировано {count} subscription(s)'
        }, status=status.HTTP_200_OK)
