# notifications.py
import logging
from asgiref.sync import sync_to_async

class NotificationService:
    def __init__(self, bot):
        """
        Инициализация сервиса уведомлений.
        :param bot: экземпляр telegram.Bot, используемый для отправки сообщений.
        """
        self.bot = bot
        self.logger = logging.getLogger(__name__)

    @sync_to_async
    def _get_all_clients(self):
        from webapp.models import Client
        # Возвращаем только клиентов, у которых telegram_id заполнен корректно
        return list(Client.objects.exclude(telegram_id__in=[None, "", "NULL"]))

    @sync_to_async
    def _prepare_results(self, results):
        # Принудительно загружаем связанные объекты через select_related
        return list(results.select_related('prize', 'participant__invoice'))

    async def notify_draw_start(self, lottery):
        """
        Уведомляет всех клиентов о запуске розыгрыша.
        :param lottery: объект розыгрыша (например, модель Lottery)
        """
        message_text = f"🎉 *Розыгрыш '{lottery.name}' начался!* Следите за обновлениями."
        clients = await self._get_all_clients()
        for client in clients:
            if not client.telegram_id:
                continue
            try:
                await self.bot.send_message(
                    chat_id=client.telegram_id,
                    text=message_text,
                    parse_mode="Markdown"
                )
            except Exception as e:
                self.logger.error(f"Ошибка отправки уведомления о запуске розыгрыша пользователю {client.telegram_id}: {e}")

    async def notify_draw_results(self, lottery, results):
        """
        Отправляет результаты розыгрыша всем клиентам.
        :param lottery: объект розыгрыша (Lottery)
        :param results: QuerySet с результатами розыгрыша (например, объекты DrawResult)
        """
        # Принудительно загружаем связанные объекты
        results_list = await self._prepare_results(results)
        message_text = f"🎉 *Результаты розыгрыша '{lottery.name}':*\n"
        for result in results_list:
            status = "✅ Подтвержден" if result.confirmed else "⏳ В ожидании подтверждения"
            prize = result.prize.reward if result.prize and hasattr(result.prize, "reward") else "неизвестно"
            account = (str(result.participant.invoice).split('/')[0].strip() 
                       if result.participant and hasattr(result.participant, "invoice") else "неизвестно")
            message_text += f"• Приз: *{prize}*, Счет: _{account}_, Статус: *{status}*\n"
        clients = await self._get_all_clients()
        for client in clients:
            if not client.telegram_id:
                continue
            try:
                await self.bot.send_message(
                    chat_id=client.telegram_id,
                    text=message_text,
                    parse_mode="Markdown"
                )
            except Exception as e:
                self.logger.error(f"Ошибка отправки результатов розыгрыша пользователю {client.telegram_id}: {e}")

    async def notify_prize_status_update(self, client, result):
        """
        Отправляет конкретному пользователю обновление по статусу подтверждения приза.
        :param client: объект клиента (Client)
        :param result: объект результата розыгрыша (DrawResult)
        """
        status = "✅ Подтвержден" if result.confirmed else "⏳ В ожидании подтверждения"
        prize = result.prize.reward if result.prize and hasattr(result.prize, "reward") else "неизвестно"
        message_text = f"🎉 *Обновление розыгрыша:*\nВаш приз *{prize}* имеет статус: *{status}*."
        try:
            if client.telegram_id:
                await self.bot.send_message(
                    chat_id=client.telegram_id,
                    text=message_text,
                    parse_mode="Markdown"
                )
        except Exception as e:
            self.logger.error(f"Ошибка отправки обновления статуса приза пользователю {client.telegram_id}: {e}")

    async def notify_binding_complete(self, client):
        """
        Уведомляет пользователя об окончании привязки клубной карты к Telegram ID.
        :param client: объект клиента (Client)
        """
        message_text = "✅ *Привязка завершена!* Ваша клубная карта успешно привязана к Telegram. Теперь вы можете участвовать в розыгрышах и чате."
        try:
            if client.telegram_id:
                await self.bot.send_message(
                    chat_id=client.telegram_id,
                    text=message_text,
                    parse_mode="Markdown"
                )
        except Exception as e:
            self.logger.error(f"Ошибка отправки уведомления о привязке пользователю {client.telegram_id}: {e}")
