#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Batch 6-step verifier: open -> snapshot text -> screenshot(+retry) -> reopen (liveness).
Usage: python3 shoot_0925.py <projects.json> <comma idxs> <shot_dir> <snap_dir>
Never calls `close --all` (that kills sibling batches). Closes only its own session.
"""
import json, io, os, subprocess, sys, time

AB = ["npx", "agent-browser", "--engine", "chrome"]
MIN_PNG = 100000


def run(args, timeout=120):
    try:
        r = subprocess.run(args, capture_output=True, text=True, timeout=timeout)
        return r.stdout + r.stderr
    except Exception as e:
        return "ERR %s" % e


def pj(out):
    s = out.find("{")
    if s < 0:
        return None
    d = 0
    for i in range(s, len(out)):
        if out[i] == "{":
            d += 1
        elif out[i] == "}":
            d -= 1
            if d == 0:
                try:
                    j = json.loads(out[s:i + 1])
                    return j["data"] if isinstance(j.get("data"), dict) else j
                except Exception:
                    return None
    return None


def ev(sess, expr, timeout=90):
    j = pj(run(AB + ["--session", sess, "--json", "eval", expr], timeout))
    return str(j.get("result")) if j and j.get("result") else ""


def main():
    pfile, idxs, shot_dir, snap_dir = sys.argv[1:5]
    projs = json.load(io.open(pfile, encoding="utf-8"))
    ids = [int(x) for x in idxs.split(",") if x.strip()]
    os.makedirs(shot_dir, exist_ok=True)
    os.makedirs(snap_dir, exist_ok=True)
    for idx in ids:
        p = projs[idx - 1]
        url = p["url"]
        sess = "sh%02d" % idx
        png = os.path.join(shot_dir, "p%02d.png" % idx)
        txtp = os.path.join(snap_dir, "s%02d.txt" % idx)
        print("=== #%d %s" % (idx, p["title"][:44]), flush=True)
        size, text, ttl2 = 0, "", ""
        for cycle in range(2):
            settle = 14 + cycle * 10
            run(AB + ["--session", sess, "--json", "open", url])
            time.sleep(settle)
            text = ev(sess, "document.body.innerText")
            if len(text) < 600:
                time.sleep(6)
                f = ev(sess, "(function(){var f=document.querySelector('iframe');if(!f)return '';"
                           "try{return f.contentDocument?f.contentDocument.body.innerText:''}"
                           "catch(e){return ''}})()")
                if f:
                    text += "\n[IFRAME]\n" + f
            if len(text) < 200:
                print("   thin text (%dch) cycle %d -> retry | %r" % (len(text), cycle, text[:120]), flush=True)
                time.sleep(8)
                continue
            for attempt in range(2):
                run(AB + ["--session", sess, "--json", "screenshot", "--full", png], 150)
                size = os.path.getsize(png) if os.path.exists(png) else 0
                if size >= MIN_PNG:
                    break
                print("   retry shot #%d size=%dB" % (attempt + 1, size), flush=True)
                ev(sess, "window.scrollTo(0, document.body.scrollHeight*0.3)")
                time.sleep(6)
            if size >= MIN_PNG:
                break
            time.sleep(6)
        # liveness re-open
        run(AB + ["--session", sess, "--json", "open", url])
        time.sleep(6)
        ttl2 = ev(sess, "document.title")
        run(AB + ["--session", sess, "close"], 40)
        if text.strip():
            head = ("项目名称：%s\n采购单位：%s\n预算金额：%s万元\n公告正文：\n%s\n发布日期：%s\n来源URL：%s\n"
                    % (p["title"], p.get("buyer", ""), p.get("budget", "未披露"), text,
                       p.get("pub_date", ""), url))
            io.open(txtp, "w", encoding="utf-8").write(head)
        print("RESULT #%d png=%dB txt=%dch live=%s" % (idx, size, len(text), ttl2[:26]), flush=True)


main()
