"""
Сервисы для работы с материалами и хранилищем.
"""

import logging
from django.db import transaction
from django.utils import timezone
from datetime import timedelta
from .models import Material, StorageQuota
from apps.subscriptions.models import Subscription
from apps.notifications.services import NotificationService

logger = logging.getLogger(__name__)


class StorageService:
    """Сервис для работы с хранилищем."""
    
    @staticmethod
    def get_storage_limit_bytes(user):
        """
        Получить лимит хранилища в байтах для пользователя.
        
        Args:
            user: Пользователь
            
        Returns:
            int: Лимит в байтах
        """
        # Получаем активную подписку
        subscription = Subscription.objects.filter(
            user=user,
            status='active'
        ).select_related('plan').first()
        
        if subscription and subscription.plan:
            # Лимит из подписки (в МБ, переводим в байты)
            return subscription.plan.max_storage_mb * 1024 * 1024
        else:
            # Базовый лимит для пользователей без подписки (100 МБ)
            return 100 * 1024 * 1024
    
    @staticmethod
    def sync_quota_with_subscription(user):
        """
        Синхронизировать квоту хранилища с подпиской пользователя.
        
        Args:
            user: Пользователь
        """
        quota, created = StorageQuota.objects.get_or_create(user=user)
        new_limit = StorageService.get_storage_limit_bytes(user)
        
        if quota.total_quota != new_limit:
            quota.total_quota = new_limit
            quota.save(update_fields=['total_quota'])
            logger.info(f'Storage quota synced for user {user.id}: {new_limit / (1024*1024):.2f} MB')
    
    @staticmethod
    def check_storage_limit(user, file_size):
        """
        Проверить, можно ли загрузить файл указанного размера.
        
        Args:
            user: Пользователь
            file_size: Размер файла в байтах
            
        Returns:
            tuple: (can_upload: bool, error_message: str or None, warning_message: str or None)
        """
        # Синхронизируем квоту с подпиской
        StorageService.sync_quota_with_subscription(user)
        
        quota, created = StorageQuota.objects.get_or_create(user=user)
        
        # Проверяем достаточно ли места
        if not quota.has_space(file_size):
            available_mb = quota.get_available_space() / (1024 * 1024)
            needed_mb = file_size / (1024 * 1024)
            total_mb = quota.total_quota / (1024 * 1024)
            used_mb = quota.used_space / (1024 * 1024)
            
            return False, f'Недостаточно места для загрузки файла ({needed_mb:.2f} МБ). Доступно: {available_mb:.2f} МБ из {total_mb:.2f} МБ (использовано: {used_mb:.2f} МБ)', None
        
        # Проверяем предупреждение о приближении к лимиту (80% и выше)
        used_percentage = quota.get_used_percentage()
        if used_percentage >= 80:
            available_mb = quota.get_available_space() / (1024 * 1024)
            total_mb = quota.total_quota / (1024 * 1024)
            warning = f'Внимание: используется {used_percentage:.1f}% хранилища. Осталось {available_mb:.2f} МБ из {total_mb:.2f} МБ'
            return True, None, warning
        
        return True, None, None
    
    @staticmethod
    def add_file_usage(user, file_size):
        """
        Добавить использование хранилища.
        
        Args:
            user: Пользователь
            file_size: Размер файла в байтах
        """
        quota, created = StorageQuota.objects.get_or_create(user=user)
        quota.add_usage(file_size)
        
        # Проверяем и отправляем уведомления о приближении к лимиту
        StorageService._check_and_notify_quota_warnings(user, quota)
    
    @staticmethod
    def remove_file_usage(user, file_size):
        """
        Убрать использование хранилища.
        
        Args:
            user: Пользователь
            file_size: Размер файла в байтах
        """
        quota, created = StorageQuota.objects.get_or_create(user=user)
        quota.remove_usage(file_size)
    
    @staticmethod
    def _check_and_notify_quota_warnings(user, quota):
        """
        Проверить квоту и отправить уведомления при необходимости.
        
        Args:
            user: Пользователь
            quota: Объект StorageQuota
        """
        used_percentage = quota.get_used_percentage()
        
        # Уведомление при 90% использования
        if used_percentage >= 90:
            NotificationService.create_notification_with_telegram(
                recipient=user,
                notification_type='system',
                title='⚠️ Хранилище почти заполнено',
                message=f'Использовано {used_percentage:.1f}% хранилища ({quota.used_space / (1024*1024):.2f} МБ из {quota.total_quota / (1024*1024):.2f} МБ). Рекомендуется освободить место.',
                priority='high',
                action_url='/materials'
            )
        # Уведомление при 80% использования (только если еще не отправляли)
        elif used_percentage >= 80:
            # Проверяем, не отправляли ли уже уведомление за последний час
            from apps.notifications.models import Notification
            recent_notification = Notification.objects.filter(
                recipient=user,
                notification_type='system',
                title__icontains='Хранилище',
                created_at__gte=timezone.now() - timedelta(hours=1)
            ).exists()
            
            if not recent_notification:
                NotificationService.create_notification_with_telegram(
                    recipient=user,
                    notification_type='system',
                    title='📦 Хранилище заполняется',
                    message=f'Использовано {used_percentage:.1f}% хранилища ({quota.used_space / (1024*1024):.2f} МБ из {quota.total_quota / (1024*1024):.2f} МБ).',
                    priority='normal',
                    action_url='/materials'
                )
    
    @staticmethod
    def get_storage_stats(user):
        """
        Получить статистику использования хранилища.
        
        Args:
            user: Пользователь
            
        Returns:
            dict: Статистика хранилища
        """
        StorageService.sync_quota_with_subscription(user)
        quota, created = StorageQuota.objects.get_or_create(user=user)
        
        # Получаем информацию о подписке
        subscription = Subscription.objects.filter(
            user=user,
            status='active'
        ).select_related('plan').first()
        
        plan_name = subscription.plan.name if subscription and subscription.plan else 'Без подписки'
        
        return {
            'total_quota_mb': quota.total_quota / (1024 * 1024),
            'used_space_mb': quota.used_space / (1024 * 1024),
            'available_space_mb': quota.get_available_space() / (1024 * 1024),
            'used_percentage': quota.get_used_percentage(),
            'plan_name': plan_name,
            'materials_count': Material.objects.filter(owner=user, is_deleted=False).count(),
        }
    
    @staticmethod
    def cleanup_old_unused_files(user, days_old=90):
        """
        Автоматическая очистка старых неиспользуемых файлов.
        
        Args:
            user: Пользователь
            days_old: Возраст файлов в днях для удаления (по умолчанию 90)
            
        Returns:
            dict: Статистика очистки
        """
        cutoff_date = timezone.now() - timedelta(days=days_old)
        
        # Находим старые материалы, которые не просматривались и не скачивались
        old_materials = Material.objects.filter(
            owner=user,
            is_deleted=False,
            created_at__lt=cutoff_date,
            views_count=0,
            downloads_count=0
        )
        
        total_size = 0
        deleted_count = 0
        
        for material in old_materials:
            if material.file:
                file_size = material.file_size or 0
                material.soft_delete()
                StorageService.remove_file_usage(user, file_size)
                total_size += file_size
                deleted_count += 1
        
        return {
            'deleted_count': deleted_count,
            'freed_space_mb': total_size / (1024 * 1024),
        }

