# -*- coding: utf-8 -*-
r"""B95: Zalo 'Trí QC' ngày 13/10 — dump khối tin + TẢI MỌI ẢNH có id >= mốc đầu ngày."""
import base64, datetime, hashlib, json, os, re, subprocess, time

S = 'tri1310'
DICH = r'C:\Claw 2\QC\images\_zalo_tri_1310'
os.makedirs(DICH, exist_ok=True)
LOG = open(r'C:\Claw 2\QC\_log_zalo_tri_1310.txt', 'a', encoding='utf-8')
MOC = int(datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp() * 1000)
log = lambda *a: (print(*a, flush=True), LOG.write(' '.join(str(x) for x in a) + '\n'), LOG.flush())


def ba(*args, timeout=240):
    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):
    return ba('--session', S, 'eval', js)


lst = ba('browser', 'list')
m = re.findall(r'(direct_local_\d+)', lst)
log('  browser id:', m[0] if m else 'KHÔNG THẤY')
if not m:
    log('  DỪNG: không có browser id'); LOG.close(); raise SystemExit(1)
log(ba('--session', S, 'browser', 'open', m[0], 'https://chat.zalo.me')[-90:])
time.sleep(16)
log('  trạng thái:', ev("JSON.stringify({t:document.title, co:!!document.querySelector('#contact-search-input')})")[-110:])
ev("(() => {const s=document.querySelector('#contact-search-input'); if(!s) return 'x'; s.focus(); document.execCommand('selectAll',false,null); document.execCommand('insertText',false,'Trí QC'); return 'ok';})()")
time.sleep(4)
log('  tìm thấy:', ev("(()=>{const a=[...document.querySelectorAll('.conv-item')].map(e=>e.innerText.split('\\n')[0]); return JSON.stringify(a.slice(0,6));})()")[-260:])
log('  mở:', ev("(()=>{const d=document.querySelector('div[id^=friend-item-].conv-item')||document.querySelector('div[id^=friend-item-]'); if(!d) return 'khong thay'; d.click(); return 'da mo';})()")[-40:])
time.sleep(5)
log('  header:', ev("(document.querySelector('.header-title')||{}).innerText||'?'")[-60:])
for i in range(6):
    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 1;})()")
    time.sleep(2)

js = """(() => {
  const blocks=[...document.querySelectorAll('.chat-message')];
  const out=blocks.map((b,i)=>{
    const t=(b.innerText||'').trim();
    const imgs=[...b.querySelectorAll('img.zimg-el')].filter(x=>/^blob:/.test(x.src||''));
    return {i:i, dai:t.length, text:t, so_anh:imgs.length,
            anh:imgs.map(x=>({id:(x.id||''), w:x.naturalWidth, h:x.naturalHeight}))};
  }).filter(x=>x.dai>0||x.so_anh);
  return JSON.stringify({tong:blocks.length, ds:out.slice(-16)});
})()"""
raw = ev(js)
p = r'C:\Claw 2\QC\_raw_zalo_tri_1310.json'
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:', j['tong'], '| có nội dung:', len(j['ds']))
can_tai = []
for x in j['ds']:
    log('   #%-3s ảnh=%-2s | %s' % (x['i'], x['so_anh'], x['text'][:150].replace('\n', ' ⏎ ')))
    for a in x['anh']:
        idd = a['id'].split('.')[0].replace('img-', '')
        if idd.isdigit() and int(idd) >= MOC:
            can_tai.append(idd)
        log('       ảnh id=%s %sx%s %s' % (idd, a['w'], a['h'], '(HÔM NAY)' if idd.isdigit() and int(idd) >= MOC else '(bỏ — trước hôm nay)'))

log('')
log('  === TẢI %d ẢNH CỦA HÔM NAY ===' % len(can_tai))
seen, n = {}, 0
for idd in can_tai:
    r = ev("(() => {const l=[...document.querySelectorAll('img.zimg-el')]; const g=l.find(x=>(x.id||'').indexOf('%s')>=0); if(!g) return 'KHONG THAY'; g.scrollIntoView({block:'center'}); if(!g.naturalWidth) return 'CHUA LOAD'; const c=document.createElement('canvas'); c.width=g.naturalWidth; c.height=g.naturalHeight; c.getContext('2d').drawImage(g,0,0,c.width,c.height); try{window.__B64=c.toDataURL('image/jpeg',0.92);}catch(e){return 'LOI';} return 'OK '+g.naturalWidth+'x'+g.naturalHeight+' '+window.__B64.length;})()" % idd)
    if not r.startswith('OK'):
        log('   id %s: %s' % (idd, r[-30:])); continue
    tong = int(r.split()[-1]); phan, vt = [], 0
    while vt < tong:
        z = ev('String(window.__B64.slice(%d,%d))' % (vt, vt + 30000)).strip()
        if z.startswith('"') and z.endswith('"'):
            z = z[1:-1]
        phan.append(z); vt += 30000
    chuoi = ''.join(phan)
    if len(chuoi) < tong * 0.9:
        log('   id %s THIẾU dữ liệu — bỏ' % idd); continue
    th = base64.b64decode(chuoi.split(',', 1)[1])
    h = hashlib.md5(th).hexdigest()[:12]
    if h in seen:
        log('   id %s TRÙNG md5 với %s' % (idd, seen[h])); continue
    n += 1
    ten = os.path.join(DICH, 'tri_1310_%02d.jpg' % n)
    open(ten, 'wb').write(th)
    seen[h] = os.path.basename(ten)
    from PIL import Image
    im = Image.open(ten)
    log('   %-22s %8d B  %sx%s  md5 %s' % (os.path.basename(ten), len(th), im.width, im.height, h))
log('  đã tải %d ảnh vào %s' % (n, DICH))
LOG.close()
