import asyncio
import socketio
import json
import uuid

class PerplexityClient:
    def __init__(self):
        # Инициализируем асинхронный клиент Socket.IO
        self.sio = socketio.AsyncClient(logger=False,
            engineio_logger=False,
            reconnection=True,
            reconnection_attempts=5,
            reconnection_delay=1,  # Начальная задержка перед переподключением
            reconnection_delay_max=10  # Максимальная задержка перед)
            )
        self.response_event = asyncio.Event()
        self.answer = None
        self.lock = asyncio.Lock()

        # Генерация заголовков
        self.custom_headers = {
            "Pragma": "no-cache",
            "Cache-Control": "no-cache",
            "User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36",
            "Origin": "https://www.perplexity.ai",
            "Accept-Encoding": "gzip, deflate, br, zstd",
            "Accept-Language": "ru-RU,ru;q=0.9",
        }

        # Привязываем обработчики событий
        self.sio.event(self.connect)
        self.sio.event(self.disconnect)
        self.sio.on('*', self.catch_all)

    def get_uuid(self):
        return str(uuid.uuid4())

    async def connect_to_server(self):
        """
        Устанавливает соединение с сервером.
        Вызывается один раз при инициализации клиента.
        """
        try:
            await self.sio.connect(
                'wss://www.perplexity.ai/socket.io',
                headers=self.custom_headers,
                transports=['websocket'],  # Используем только WebSocket транспорт
               # ssl_verify=False  # Отключаем проверку SSL сертификата, если необходимо
            )
            print("Соединение установлено.")
        except Exception as e:
            print(f"Ошибка при подключении: {e}")
            raise

    async def disconnect_from_server(self):
        """
        Закрывает соединение с сервером.
        """
        await self.sio.disconnect()
        print("Соединение закрыто.")

    async def ask_question(self, question: str) -> str:
        """
        Отправляет вопрос и ожидает ответа.

        :param question: Вопрос для отправки.
        :return: Ответ от сервера.
        """
        async with self.lock:
            # Сброс предыдущего ответа
            self.answer = None
            self.response_event.clear()

            # Отправляем событие 'perplexity_ask' с заданным вопросом
            await self.sio.emit(
                "perplexity_ask",
                (
                    question,
                    {
                        "version": "2.13",
                        "source": "mweb",
                        "attachments": [],
                        "language": "ru-RU",
                        "timezone": "Asia/Yekaterinburg",
                        "search_focus": "internet",
                        "sources": ["web"],
                        "frontend_uuid": self.get_uuid(),
                        "mode": "copilot",  # Или "concise" в зависимости от необходимого режима
                        "is_related_query": False,
                        "visitor_id": self.get_uuid(),
                        "frontend_context_uuid": self.get_uuid(),
                        "prompt_source": "user",
                        "query_source": "home",
                        "is_incognito": False,
                        "time_from_first_type": 5127
                    }
                )
            )

            # Ждем ответа
            try:
                await asyncio.wait_for(self.response_event.wait(), timeout=120)  # Таймаут 120 секунд
            except asyncio.TimeoutError:
                print("Время ожидания ответа истекло.")
                raise TimeoutError("Ответ не получен в течение 120 секунд.")

            if self.answer:
                return self.answer
            else:
                raise ValueError("Ответ не был получен.")

    async def catch_all(self, event, data):
        """
        Обработчик всех событий.
        """
        try:
            status = data.get("status")
            final = data.get("final", False)
            text = data.get("text", "")

            if final:
                parsed = json.loads(text)
                self.answer = parsed.get("answer", "")
                self.response_event.set()

        except Exception as e:
            print(f"Ошибка при обработке события: {e}")
            self.response_event.set()

    async def connect(self):
        """
        Обработчик успешного подключения.
        """
        print("Подключено к серверу")

    async def disconnect(self):
        """
        Обработчик отключения от сервера.
        """
        print("Отключено от сервера")


# Пример использования класса
async def main():
    client = PerplexityClient()
    await client.connect_to_server()
    try:
        question1 = "Напиши полный текст гимна России"
        response1 = await client.ask_question(question1)
        print(f"Ответ на первый вопрос: {response1}")
        await asyncio.sleep(200)
        question2 = "Новости дня"
        response2 = await client.ask_question(question2)
        print(f"Ответ на второй вопрос: {response2}")

        # Можно добавить больше вопросов по мере необходимости
    except Exception as e:
        print(f"Произошла ошибка: {e}")
    finally:
        await client.disconnect_from_server()


if __name__ == "__main__":
    asyncio.run(main()) сделай для каждого запроса к функции создание нового соединения заново, т.к. я редко использую функцию. Объект Класса при этом часто будет один