import asyncio, json, logging
from playwright.async_api import async_playwright, Page
from telegram import Bot

log = logging.getLogger(__name__)
MAX_URL = "https://web.max.ru"

async def check_logged_in(page: Page) -> bool:
    return await page.evaluate("""
        () => { const a = localStorage.getItem('__oneme_auth');
            if (!a) return false;
            try { return !!JSON.parse(a).token; } catch(e) { return false; } }
    """)

async def get_chats(page: Page) -> list:
    return await page.evaluate("""
        () => {
            const items = [];
            document.querySelectorAll('.cell.svelte-q2jdqb').forEach((el, idx) => {
                const nameEl = el.querySelector('.name .text');
                const unreadEl = el.querySelector('.badgeIcon .text, [class*="badgeIcon"] [class*="text"]');
                const unreadCount = unreadEl ? parseInt(unreadEl.innerText.trim()) || 0 : 0;
                items.push({ index: idx,
                    name: nameEl ? nameEl.innerText.trim() : `Чат ${idx}`,
                    unreadCount, isMuted: !!el.querySelector('.iconMute') });
            });
            return items;
        }
    """)

async def send_webpush(sub_json: str, title: str, body: str,
                       vapid_private: str, vapid_email: str):

    try:
        from pywebpush import webpush

        webpush(
                subscription_info=json.loads(sub_json),
                data=json.dumps({"title": title, "body": body}),
                vapid_private_key="/var/www/html/maxservice/private.pem",
                vapid_claims={
                    "sub": f"mailto:{vapid_email}"
                }
            )

    except Exception as e:
        log.error(f"WebPush error: {e}")

class UserWorker:
    def __init__(self, user_id, telegram_chat_id, session_json, bot: Bot,
                 poll_interval=300, mute_filter=True,
                 notify_telegram=False, notify_webpush=False,
                 push_subscription=None, vapid_private=None, vapid_email=None,
                 on_session_expired=None):
        self.user_id = user_id
        self.telegram_chat_id = telegram_chat_id
        self.session_json = session_json
        self.bot = bot
        self.poll_interval = poll_interval
        self.mute_filter = mute_filter
        self.notify_telegram = notify_telegram
        self.notify_webpush = notify_webpush
        self.push_subscription = push_subscription
        self.vapid_private = vapid_private
        self.vapid_email = vapid_email
        self.on_session_expired = on_session_expired
        self.running = False
        self.prev_unread: dict = {}
        self._task = None

    def start(self): self._task = asyncio.create_task(self._run())
    def stop(self):
        self.running = False
        if self._task: self._task.cancel()

    async def notify(self, chat_name: str, count: int):
        text = f"🟢 {chat_name}: {count} новых"
        tasks = []
        if self.notify_telegram and self.telegram_chat_id:
            tasks.append(self._send_tg(text))
        if self.notify_webpush and self.push_subscription:
            tasks.append(send_webpush(self.push_subscription, "MAX Bridge", text,
                self.vapid_private, self.vapid_email))
        if tasks:
            await asyncio.gather(*tasks, return_exceptions=True)

    async def _send_tg(self, text):
        try:
            await self.bot.send_message(chat_id=self.telegram_chat_id, text=text)
        except Exception as e:
            log.error(f"TG error user {self.user_id}: {e}")

    async def _run(self):
        self.running = True
        log.info(f"[{self.user_id}] Старт. TG={self.notify_telegram} Push={self.notify_webpush} interval={self.poll_interval}s")
        async with async_playwright() as pw:
            browser = await pw.chromium.launch(headless=True)
            context = await browser.new_context(storage_state=json.loads(self.session_json))
            page = await context.new_page()
            await page.goto(MAX_URL, wait_until="networkidle")
            await page.wait_for_timeout(3000)
            if not await check_logged_in(page):
                log.warning(f"[{self.user_id}] Сессия истекла")
                if self.on_session_expired: await self.on_session_expired(self.user_id)
                await browser.close()
                return
            error_count = 0
            while self.running:
                try:
                    chats = await get_chats(page)
                    if not chats:
                        await page.reload(wait_until="networkidle")
                        await page.wait_for_timeout(3000)
                    else:
                        for chat in chats:
                            if self.mute_filter and chat.get("isMuted"): continue
                            name, cur = chat["name"], chat.get("unreadCount", 0)
                            prev = self.prev_unread.get(name, 0)
                            if cur > prev: await self.notify(name, cur)
                            self.prev_unread[name] = cur
                    error_count = 0
                except Exception as e:
                    error_count += 1
                    log.error(f"[{self.user_id}] Ошибка #{error_count}: {e}")
                    if error_count >= 5:
                        if self.on_session_expired: await self.on_session_expired(self.user_id)
                        break
                await asyncio.sleep(self.poll_interval)
            await browser.close()
