import asyncio
from collections import deque
from datetime import datetime
import time
from playwright.async_api import Page


class NetworkIdleWaiter:
    """
    Класс для продвинутого ожидания.

    Запускает таймер и сбрасывает его после каждого загруженного файла.
    Спустя заданное время после последней активности разблокирует поток.
    """
    def __init__(
            self,
            page: Page,
            idle_time: float = 1.0,
            timeout: float = 10.0,
            ignore_resources: list = None,
            print_on: bool = False,
    ):
        self.page = page
        self.idle_time = idle_time
        self.timeout = timeout
        self.ignore_resources = ignore_resources or ['font', 'websocket']

        self.pending_requests = {}
        self.last_activity = time.time()
        self.network_log = deque(maxlen=100)  # Последние 100 запросов для отладки

        self.print_on = print_on

    async def wait(self):
        """Ждет пока сеть станет неактивной"""

        # Подписываемся на события
        self.page.on("request", self._on_request)
        self.page.on("response", self._on_response)
        self.page.on("requestfailed", self._on_request_failed)

        start_time = time.time()

        try:
            while True:
                await asyncio.sleep(0.1)

                current_time = time.time()
                idle_duration = current_time - self.last_activity

                # Проверяем условия выхода
                if len(self.pending_requests) == 0 and idle_duration >= self.idle_time:
                    if self.print_on:
                        print(f"✅ Сеть неактивна {idle_duration:.1f} сек. "
                              f"Загрузка завершена!")
                    break

                # Проверка таймаута
                if current_time - start_time > self.timeout:
                    if self.print_on:
                        print(f"⚠️ Таймаут {self.timeout} сек. "
                              f"Остались запросы: {len(self.pending_requests)}")
                        if self.pending_requests:
                            print("Незавершенные запросы:")
                            for url, info in list(self.pending_requests.items())[:5]:
                                print(f"  - {info['type']}: {url[:100]}...")
                    break

                # Отладочная информация
                if self.print_on:
                    if len(self.pending_requests) > 0:
                        print(f"⏳ Ожидание... Активных запросов: {len(self.pending_requests)}, "
                              f"Idle: {idle_duration:.1f}s")

        finally:
            # Отписываемся от событий
            self.page.remove_listener("request", self._on_request)
            self.page.remove_listener("response", self._on_response)
            self.page.remove_listener("requestfailed", self._on_request_failed)

    def get_stats(self):
        """Получить статистику по сетевой активности"""
        return {
            'total_requests': len(self.network_log),
            'pending': len(self.pending_requests),
            'last_activity': self.last_activity,
            'log': list(self.network_log)
        }

    # Обработчики событий
    def _on_request(self, request):
        # Игнорируем определенные типы ресурсов
        if request.resource_type in self.ignore_resources:
            return

        self.pending_requests[request.url] = {
            'start': time.time(),
            'type': request.resource_type,
            'method': request.method
        }
        self.last_activity = time.time()

        self.network_log.append({
            'event': 'request',
            'url': request.url,
            'type': request.resource_type,
            'time': datetime.now().isoformat()
        })

    def _on_response(self, response):
        if response.url in self.pending_requests:
            request_info = self.pending_requests.pop(response.url)
            duration = time.time() - request_info['start']

            self.network_log.append({
                'event': 'response',
                'url': response.url,
                'status': response.status,
                'duration': duration,
                'time': datetime.now().isoformat()
            })

        self.last_activity = time.time()

    def _on_request_failed(self, request):
        if request.url in self.pending_requests:
            self.pending_requests.pop(request.url)

            self.network_log.append({
                'event': 'failed',
                'url': request.url,
                'failure': request.failure,
                'time': datetime.now().isoformat()
            })

        self.last_activity = time.time()
