# -*- coding: utf-8 -*-
"""B30: mở Zalo (Chrome thật) -> hội thoại 'Loc QC ( So 2)' -> bóc NGUYÊN VĂN tin nhắn của Lộc.
Lưu raw JSON để đối chiếu byte-exact. Chạy nền, ghi log."""
import json, os, re, subprocess, sys, time

S = 'loc1010'
LOG = open(r'C:\Claw 2\QC\_log_zalo_loc_1010.txt', 'a', encoding='utf-8')


def log(*a):
    s = ' '.join(str(x) for x in a)
    print(s, flush=True); LOG.write(s + '\n'); LOG.flush()


def ba(*args, timeout=200):
    try:
        r = subprocess.run(['browser-act'] + list(args), capture_output=True, text=True,
                           encoding='utf-8', errors='replace', timeout=timeout)
        return ((r.stdout or '') + (r.stderr or '')).strip()
    except subprocess.TimeoutExpired:
        return 'TIMEOUT'


def ev(js, timeout=200):
    return ba('--session', S, 'eval', js, timeout=timeout)


# 1) danh sách browser
lst = ba('browser', 'list')
log('=== browser list ===')
log(lst[-600:])
m = re.search(r'id=(direct_local_\d+)', lst)
if not m:
    log('KHÔNG có direct_local_* trong danh sách — tạo mới')
    c = ba('browser', 'create', '--type', 'chrome-direct', '--name', 'Chrome may Anh Minh',
           '--desc', 'Doc bao cao QC tren Zalo')
    log(c[-400:])
    lst = ba('browser', 'list')
    m = re.search(r'id=(direct_local_\d+)', lst)
ID = m.group(1) if m else None
log('dùng browser id:', ID)

# 2) mở Zalo
log('=== mở Zalo ===')
log(ba('--session', S, 'browser', 'open', ID, 'https://chat.zalo.me')[-300:])
time.sleep(16)
r = ev("JSON.stringify({title:document.title, co_input:!!document.querySelector('#contact-search-input')})")
log('trạng thái:', r[-200:])

# 3) tìm + mở hội thoại Lộc
log('=== mở hội thoại ===')
js_mo = """(() => {
  const s = document.querySelector('#contact-search-input');
  if (!s) return 'khong co o tim kiem';
  s.focus();
  document.execCommand('selectAll', false, null);
  document.execCommand('insertText', false, 'Loc QC');
  return 'da go tu khoa';
})()"""
log(ev(js_mo)[-120:])
time.sleep(4)
log(ev("(()=>{const a=[...document.querySelectorAll('.conv-item')].map(e=>e.innerText.split('\\n')[0]); return JSON.stringify(a.slice(0,8));})()")[-300:])
log(ev("(()=>{const d=document.querySelector('div[id^=friend-item-].conv-item')||document.querySelector('div[id^=friend-item-]'); if(!d) return 'khong thay dong lien he'; d.click(); return 'da bam';})()")[-120:])
time.sleep(5)
log('header:', ev("(document.querySelector('.header-title')||{}).innerText||'?'")[-160:])

# 4) cuộn lên vài vòng rồi bóc tin
log('=== cuộn + bóc tin ===')
for i in range(4):
    ev("(()=>{const c=[...document.querySelectorAll('div,section,ul')].filter(e=>e.scrollHeight>e.clientHeight+200); c.sort((a,b)=>b.scrollHeight-a.scrollHeight); if(c[0]){c[0].scrollTop=c[0].scrollTop-1500;} return 'cuon';})()")
    time.sleep(2)
js_dump = """(() => {
  const blocks = [...document.querySelectorAll('.chat-message')];
  const out = blocks.map((b, i) => {
    const t = (b.innerText || '').trim();
    const imgs = [...b.querySelectorAll('img')].filter(x => /zimg-el/.test(x.className||'') && /^blob:/.test(x.src||'')).length;
    const files = [...b.querySelectorAll('.file-message__container')].length;
    return {i: i, cls: b.className, dai: t.length, text: t, so_anh: imgs, so_file: files};
  }).filter(x => x.dai > 0 || x.so_anh || x.so_file);
  return JSON.stringify({tong_khoi: blocks.length, co_noi_dung: out.length, ds: out.slice(-40)});
})()"""
raw = ev(js_dump)
p = r'C:\Claw 2\QC\_raw_zalo_loc_1010.json'
try:
    j = json.loads(raw[raw.index('{'):raw.rindex('}') + 1])
    json.dump(j, open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
    log('tổng khối .chat-message:', j['tong_khoi'], '| khối có nội dung:', j['co_noi_dung'])
    for x in j['ds'][-12:]:
        me = ' [ME]' if re.search(r'\bme\b', x['cls']) else ''
        log('  #%s%s dài=%s ảnh=%s file=%s | %s' % (x['i'], me, x['dai'], x['so_anh'], x['so_file'], x['text'][:150].replace('\n', ' ⏎ ')))
except Exception as e:
    log('LỖI parse:', e, raw[:400])
log('đã lưu raw:', p)
LOG.close()
