"""
Get cookies from Surebet247 and use them to connect to the WS directly.
"""
import json
import asyncio
import threading
import time
import msgpack
import websocket
from playwright.async_api import async_playwright

WS_BASE = (
    'wss://sport-iframe.serhjs.xyz/direct-feed/feed'
    '?brand=CL38B1'
    '&X-Api-Key=b8b92942-ce6a-44e8-a5d5-6bf407e316a2'
)
CONTEXT = ['en', 'MOBILE_WEB', 'CL38B1', '', 'NGN']
_req_id = [0]


def make_request(method: str, args: list) -> bytes:
    _req_id[0] += 1
    rid = str(_req_id[0])
    body = msgpack.packb([4, {}, rid, method, args], use_bin_type=True)
    return bytes([len(body)]) + body


def decode_frame(data: bytes):
    for skip in (1, 2, 3, 0):
        try:
            return msgpack.unpackb(data[skip:], raw=False, strict_map_key=False)
        except Exception:
            pass
    return None


async def get_ws_headers():
    """Use Playwright to get cookies + headers from the actual connection."""
    ws_headers = {}
    cookies_str = ''
    got_info = asyncio.Event()

    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True, args=['--no-sandbox'])
        ctx = await browser.new_context(
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        )
        page = await ctx.new_page()

        def on_ws(ws):
            url = ws.url
            if 'direct-feed' in url:
                print(f'[Playwright WS] {url[:100]}')

                def on_recv(payload):
                    print(f'  [RECV] {str(payload)[:100]}')
                    got_info.set()

                ws.on('framereceived', on_recv)

        page.on('websocket', on_ws)

        await page.goto('https://www.surebet247.com/sport/football', wait_until='domcontentloaded', timeout=30000)
        await asyncio.sleep(5)

        # Capture cookies
        all_cookies = await ctx.cookies()
        cookie_parts = [f"{c['name']}={c['value']}" for c in all_cookies]
        cookies_str = '; '.join(cookie_parts)

        # Try to get the WS headers from request interception
        await asyncio.wait_for(got_info.wait(), timeout=10)

        await browser.close()

    return cookies_str


async def main():
    print('Getting cookies from browser session...')
    try:
        cookies_str = await get_ws_headers()
        print(f'Cookies: {cookies_str[:200]}')
    except Exception as e:
        print(f'Browser error: {e}')
        cookies_str = ''

    # Now try direct WS with cookies
    print('\nAttempting direct WS connection with cookies...')
    results = {}
    done = threading.Event()
    handshake_done = [False]
    _req_id[0] = 0

    def on_open(ws):
        print('[WS] Connected, sending protocol negotiation')
        ws.send('{"protocol":"messagepack","version":1}')

    def on_message(ws, msg):
        if isinstance(msg, str):
            print(f'[TEXT] {msg[:200]}')
            return
        if not handshake_done[0]:
            print(f'[HANDSHAKE OK] server ack: {msg[:20]}')
            handshake_done[0] = True
            # Send GetSportsByStage
            req = make_request('GetSportsByStage', [3, CONTEXT])
            print(f'[→] GetSportsByStage ({len(req)} bytes)')
            ws.send(req, opcode=websocket.ABNF.OPCODE_BINARY)
            return

        decoded = decode_frame(msg)
        if decoded:
            rid = decoded[2] if len(decoded) > 2 else '?'
            result = decoded[4] if len(decoded) > 4 else (decoded[3] if len(decoded) > 3 else None)
            print(f'\n[REPLY id={rid}]')
            print(json.dumps(result, default=str, ensure_ascii=False)[:2000])
            results[rid] = result

            if rid == '1':  # GetSportsByStage done
                req = make_request('GetEventsBySportAndTimeRange', ['F', [0, 24], CONTEXT])
                print(f'[→] GetEventsBySportAndTimeRange ({len(req)} bytes)')
                ws.send(req, opcode=websocket.ABNF.OPCODE_BINARY)
            elif rid == '2':
                done.set()
        else:
            print(f'[BIN] Cannot decode ({len(msg)} bytes): {msg[:30]}')

    def on_error(ws, err):
        print(f'[ERR] {err}')
        done.set()

    def on_close(ws, code, msg):
        print(f'[CLOSE] {code}')
        done.set()

    headers = {
        'Origin': 'https://sport-iframe.serhjs.xyz',
        'Referer': 'https://www.surebet247.com/sport/football',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    }
    if cookies_str:
        headers['Cookie'] = cookies_str

    ws = websocket.WebSocketApp(WS_BASE, header=headers,
                                on_open=on_open, on_message=on_message,
                                on_error=on_error, on_close=on_close)
    t = threading.Thread(target=ws.run_forever, daemon=True)
    t.start()
    done.wait(timeout=20)
    ws.close()


asyncio.run(main())
