# -*- coding: utf-8 -*-
"""点击封面区域 + CDP 拦截文件选择器 → 设置文件"""
import sys, socket, json, time, os, glob
sys.stdout.reconfigure(encoding="utf-8")

HOST = "localhost"
PORT = 28800
PAGE_ID = "70039F329097C14448996F189E3A42A1"

imgs = glob.glob(r"D:\wxpic\*.jpg") + glob.glob(r"D:\wxpic\*.png")
IMG = max(imgs, key=os.path.getmtime) if imgs else None
print("[INFO] 图片:", IMG)

def make_ws():
    import urllib.parse
    u = "ws://%s:%s/devtools/page/%s" % (HOST, PORT, PAGE_ID)
    p = urllib.parse.urlparse(u)
    s = socket.create_connection((p.hostname, p.port or 80), timeout=15)
    req = (
        "GET %s HTTP/1.1\r\nHost: %s:%s\r\nUpgrade: websocket\r\n"
        "Connection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
        "Sec-WebSocket-Version: 13\r\n\r\n"
    ) % (p.path, p.hostname, p.port)
    s.send(req.encode())
    resp = b""
    while b"\r\n\r\n" not in resp:
        resp += s.recv(4096)
    return s

def ws_send(sock, data):
    data = data.encode("utf-8")
    n = len(data)
    m = b"\x01\x02\x03\x04"
    if n <= 125:
        h = bytes([0x81, n | 0x80]) + m
    elif n <= 65535:
        h = bytes([0x81, 0xFE]) + n.to_bytes(2, "big") + m
    else:
        h = bytes([0x81, 0xFF]) + n.to_bytes(8, "big") + m
    sock.send(h + bytes(data[i] ^ m[i % 4] for i in range(n)))

def ws_recv(sock):
    h = b""
    while len(h) < 2:
        h += sock.recv(2 - len(h))
    n = h[1] & 0x7F
    if n == 126:
        nb = b""
        while len(nb) < 2:
            nb += sock.recv(2 - len(nb))
        n = int.from_bytes(nb, "big")
    elif n == 127:
        nb = b""
        while len(nb) < 8:
            nb += sock.recv(8 - len(nb))
        n = int.from_bytes(nb, "big")
    body = b""
    while len(body) < n:
        body += sock.recv(n - len(body))
    return body.decode("utf-8")

_mid = [0]
events = []

def cdp_send(sock, method, params=None):
    if params is None:
        params = {}
    _mid[0] += 1
    ws_send(sock, json.dumps({"id": _mid[0], "method": method, "params": params}))
    return _mid[0]

def cdp_wait(sock, mid, timeout=20):
    sock.settimeout(timeout)
    for _ in range(300):
        try:
            r = json.loads(ws_recv(sock))
            events.append(r)
            if r.get("id") == mid:
                return r
            # 检查是否是 FileChooser 事件
            if r.get("method") == "Page.fileChooserOpened":
                return r
        except Exception:
            pass
    return None

def cdp_sync(sock, method, params=None):
    mid = cdp_send(sock, method, params)
    return cdp_wait(sock, mid)

sock = make_ws()
print("[OK] Connected\n")

# Step 1: 启用 Page domain（监听 fileChooserOpened 事件）
print("[1] Page.enable...")
r = cdp_sync(sock, "Page.enable")
print("  result:", "OK" if r and "result" in r else "FAIL")

# Step 2: 启用文件选择器拦截
print("\n[2] Page.setInterceptFileChooserDialog...")
r = cdp_sync(sock, "Page.setInterceptFileChooserDialog", {"enabled": True})
print("  result:", r)

# Step 3: 点击封面区域（"选择封面" div）
print("\n[3] 点击封面区域...")
r = cdp_sync(sock, "Runtime.evaluate", {
    "expression": """
    (function() {
        var el = document.querySelector('._73a3a52aab7e3a36-default') || 
                document.querySelector('[class*="73a3a52aab7e3a36"]');
        if (!el) return 'element not found';
        el.scrollIntoView();
        el.click();
        return 'clicked';
    })()
    """,
    "returnByValue": True
})
val = r.get("result", {}).get("result", {}).get("value", "") if r else ""
print("  click result:", val)

time.sleep(1)

# Step 4: 收集事件
print("\n[4] 等待 FileChooser 事件...")
sock.settimeout(5)
try:
    while True:
        r = json.loads(ws_recv(sock))
        events.append(r)
        print("  event:", r.get("method", "?") if isinstance(r, dict) else str(r)[:100])
        if r.get("method") == "Page.fileChooserOpened":
            break
except socket.timeout:
    print("  timeout waiting for event")

# 检查收集到的事件
for ev in events:
    if ev.get("method") == "Page.fileChooserOpened":
        frame_id = ev["params"].get("frameId", "?")
        mode = ev["params"].get("mode", "?")
        print("\n  FileChooser opened! frameId=%s mode=%s" % (frame_id, mode))
        
        # Step 5: 用 DOM.setFileInputFiles 设置文件（用 JS 返回 objectId）
        # 先找新创建的 file input
        r = cdp_sync(sock, "Runtime.evaluate", {
            "expression": """
            (function() {
                var inputs = document.querySelectorAll('input[type=file]');
                var result = [];
                for (var i = 0; i < inputs.length; i++) {
                    result.push({
                        index: i, 
                        accept: inputs[i].accept, 
                        id: inputs[i].id,
                        name: inputs[i].name
                    });
                }
                return JSON.stringify(result);
            })()
            """,
            "returnByValue": True
        })
        val = r.get("result", {}).get("result", {}).get("value", "") if r else ""
        print("  current file inputs:", val)
        
        # 用 objectId 方式
        r = cdp_sync(sock, "Runtime.evaluate", {
            "expression": "document.querySelector('input[type=file]:not([accept*=video])')",
            "returnByValue": False
        })
        obj_id = None
        if r and "result" in r:
            obj_id = r["result"].get("result", {}).get("objectId")
            print("  objectId:", obj_id)
        
        if obj_id:
            print("\n[5] DOM.setFileInputFiles via objectId...")
            r = cdp_sync(sock, "DOM.setFileInputFiles", {
                "objectId": obj_id,
                "files": [IMG]
            })
            print("  result:", r)

# 关闭拦截
cdp_sync(sock, "Page.setInterceptFileChooserDialog", {"enabled": False})
sock.close()
print("\nDone")
