import json
import urllib.request
import websocket

CDP_HTTP = "http://127.0.0.1:18800/json"


def get_json(url):
    with urllib.request.urlopen(url) as r:
        return json.load(r)


def cdp_send(ws, method, params=None):
    cdp_send.counter += 1
    msg = {"id": cdp_send.counter, "method": method, "params": params or {}}
    ws.send(json.dumps(msg))
    while True:
        raw = ws.recv()
        data = json.loads(raw)
        if data.get("id") == cdp_send.counter:
            return data


cdp_send.counter = 0


def main():
    tabs = get_json(CDP_HTTP)
    page = next(
        (t for t in tabs if t.get("type") == "page" and "studio.youtube.com" in t.get("url", "") and "/comments/inbox" in t.get("url", "")),
        None,
    )
    if not page:
        raise SystemExit("No studio inbox page found")

    ws = websocket.create_connection(page["webSocketDebuggerUrl"], timeout=30)
    try:
        cdp_send(ws, "Page.enable")
        cdp_send(ws, "Runtime.enable")
        cdp_send(ws, "Page.bringToFront")
        expr = r'''new Promise(async (resolve) => {
  const sleep = ms => new Promise(r => setTimeout(r, ms));
  const norm = s => (s || '').replace(/\s+/g, ' ').trim();
  const first3 = s => norm(s).split(/\s+/).filter(Boolean).slice(0,3).join(' ') || 'no visible';
  const timeFrom = s => {
    const m = norm(s).match(/hace\s+\d+\s+(?:mes|meses|semana|semanas|día|días|hora|horas|minuto|minutos|año|años)/i);
    return m ? m[0].trim() : 'no visible';
  };
  const seen = new Map();
  const scrollers = () => [...document.querySelectorAll('*')]
    .filter(el => el.scrollHeight > el.clientHeight + 120 && el.clientHeight > 180)
    .sort((a,b) => (b.scrollHeight-b.clientHeight)-(a.scrollHeight-a.clientHeight));
  const collect = () => {
    const threads = [...document.querySelectorAll('ytcp-comment-thread')];
    for (const th of threads) {
      const usuario = norm(th.querySelector('#name')?.textContent) || 'no visible';
      const texto = norm(th.querySelector('#content-text')?.textContent) || 'no visible';
      const video = first3(th.querySelector('#video-title')?.textContent || '');
      const tiempo = timeFrom(th.querySelector('#body')?.textContent || '');
      const allText = norm(th.textContent || '');
      let estado = 'no';
      if (/\b0 respuestas\b/i.test(allText)) estado = 'no';
      else if (/\b[1-9]\d*\s+respuestas?\b/i.test(allText)) estado = 'no claro';
      const key = `${usuario}||${tiempo}||${texto}`;
      if (!seen.has(key)) seen.set(key, { usuario, tiempo, video, texto, respuestaDelCanal: estado });
    }
  };
  let last = 0, stable = 0;
  for (let i = 0; i < 140; i++) {
    collect();
    const sc = scrollers()[0];
    if (sc) sc.scrollTop = Math.min(sc.scrollTop + Math.max(500, sc.clientHeight * 0.9), sc.scrollHeight);
    window.scrollBy(0, 250);
    await sleep(900);
    if (seen.size === last) stable++; else stable = 0;
    last = seen.size;
    if (stable >= 14) break;
  }
  collect();
  resolve(JSON.stringify({
    title: document.title,
    chips: [...document.querySelectorAll('ytcp-filter-chip')].map(el => norm(el.textContent)).filter(Boolean),
    total: seen.size,
    rows: [...seen.values()]
  }));
})'''
        res = cdp_send(ws, "Runtime.evaluate", {"expression": expr, "awaitPromise": True, "returnByValue": True})
        value = res.get("result", {}).get("result", {}).get("value")
        print(value)
    finally:
        ws.close()


if __name__ == "__main__":
    main()
