# -*- coding: utf-8 -*-
"""
设置封面 - 从正文选择第一张图
这是已验证可行的方案（参考微信公众号 Skill）
"""
import sys, socket, json, time
import urllib.request

HOST = "127.0.0.1"
PORT = 9222

# 获取页面 ID
pages = json.loads(urllib.request.urlopen(f'http://{HOST}:{PORT}/json', timeout=5).read())
page = None
for p in pages:
    if 'baijiahao' in p.get('url', '') and 'edit' in p.get('url', ''):
        page = p
        break

if not page:
    print("[ERROR] 未找到百家号编辑器页面")
    sys.exit(1)

PAGE_ID = page['id']
print(f"[OK] Page ID: {PAGE_ID[:20]}...")

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

def send(s, d):
    d = d.encode('utf-8')
    n = len(d)
    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
    s.send(h + bytes(d[i] ^ m[i % 4] for i in range(n)))

def recv(s):
    def rx(n):
        b = b''
        while len(b) < n:
            b += s.recv(n - len(b))
        return b
    h = rx(2)
    n = h[1] & 0x7f
    if n == 126:
        n = int.from_bytes(rx(2), 'big')
    elif n == 127:
        n = int.from_bytes(rx(8), 'big')
    return rx(n).decode('utf-8')

_mid = 0
def call(s, js, timeout=20):
    global _mid
    _mid += 1
    send(s, json.dumps({
        'id': _mid,
        'method': 'Runtime.evaluate',
        'params': {'expression': js, 'returnByValue': True}
    }))
    s.settimeout(timeout)
    for _ in range(300):
        try:
            r = json.loads(recv(s))
            if r.get('id') == _mid:
                return r.get('result', {}).get('result', {}).get('value', '')
        except:
            pass
    return ''

def mouse_click(s, x, y):
    global _mid
    for t in ['mousePressed', 'mouseReleased']:
        _mid += 1
        send(s, json.dumps({
            'id': _mid,
            'method': 'Input.dispatchMouseEvent',
            'params': {'type': t, 'x': x, 'y': y, 'button': 'left', 'clickCount': 1}
        }))
        recv(s)
        time.sleep(0.05)

sock = ws(PAGE_ID)
print("[OK] 已连接\n")

# Step 1: 点击封面区域（打开选择封面弹窗）
print("[Step 1] 点击封面区域...")
r = call(sock, """
(function() {
    // 找封面区域
    var all = document.querySelectorAll('*');
    for (var el of all) {
        var t = (el.innerText || '').trim();
        if (t === '选择封面') {
            var rect = el.getBoundingClientRect();
            return JSON.stringify({
                x: Math.round(rect.left + rect.width / 2),
                y: Math.round(rect.top + rect.height / 2),
                found: true
            });
        }
    }
    return JSON.stringify({found: false});
})()
""")
print(f"  封面位置: {r}")

if r and 'found' in r:
    try:
        info = json.loads(r)
        if info.get('found'):
            x, y = info['x'], info['y']
            print(f"  点击封面区域 ({x}, {y})...")
            mouse_click(sock, x, y)
            time.sleep(2)
    except:
        print("  点击失败，继续尝试其他方法...")

# Step 2: 找"从正文选择"按钮并点击
print("\n[Step 2] 找'从正文选择'按钮...")
r = call(sock, """
(function() {
    var all = document.querySelectorAll('*');
    for (var el of all) {
        var t = (el.innerText || '').trim();
        if (t.includes('从正文选择') || t.includes('从正文')) {
            var rect = el.getBoundingClientRect();
            return JSON.stringify({
                x: Math.round(rect.left + rect.width / 2),
                y: Math.round(rect.top + rect.height / 2),
                text: t,
                found: true
            });
        }
    }
    return JSON.stringify({found: false});
})()
""")
print(f"  按钮位置: {r}")

if r and 'found' in r:
    try:
        info = json.loads(r)
        if info.get('found'):
            x, y = info['x'], info['y']
            print(f"  点击'从正文选择' ({x}, {y})...")
            mouse_click(sock, x, y)
            time.sleep(3)
    except:
        print("  点击失败")

# Step 3: 在弹窗中选择第一张图片
print("\n[Step 3] 选择第一张图片...")
r = call(sock, """
(function() {
    // 找弹窗中的图片列表
    var imgs = document.querySelectorAll('li.appmsg_content_img_item, .img-item, [class*="img"][class*="item"]');
    if (imgs.length > 0) {
        var first = imgs[0];
        var rect = first.getBoundingClientRect();
        return JSON.stringify({
            x: Math.round(rect.left + rect.width / 2),
            y: Math.round(rect.top + rect.height / 2),
            count: imgs.length,
            found: true
        });
    }
    // 备选：找所有图片
    var allImgs = document.querySelectorAll('img');
    for (var img of allImgs) {
        var rect = img.getBoundingClientRect();
        if (rect.width > 50 && rect.height > 50) {
            return JSON.stringify({
                x: Math.round(rect.left + rect.width / 2),
                y: Math.round(rect.top + rect.height / 2),
                count: 1,
                found: true,
                method: 'img'
            });
        }
    }
    return JSON.stringify({found: false});
})()
""")
print(f"  图片位置: {r}")

if r and 'found' in r:
    try:
        info = json.loads(r)
        if info.get('found'):
            x, y = info['x'], info['y']
            print(f"  点击第一张图片 ({x}, {y})...")
            mouse_click(sock, x, y)
            time.sleep(2)
    except:
        print("  点击失败")

# Step 4: 点击"下一步"或"确定"按钮
print("\n[Step 4] 点击确定...")
time.sleep(2)
r = call(sock, """
(function() {
    var all = document.querySelectorAll('button, a, div[role="button"]');
    for (var el of all) {
        var t = (el.innerText || '').trim();
        if (t === '确定' || t === '下一步' || t === '确认' || t.includes('确定')) {
            var rect = el.getBoundingClientRect();
            if (rect.width > 30 && rect.height > 20) {
                return JSON.stringify({
                    x: Math.round(rect.left + rect.width / 2),
                    y: Math.round(rect.top + rect.height / 2),
                    text: t,
                    found: true
                });
            }
        }
    }
    return JSON.stringify({found: false});
})()
""")
print(f"  按钮位置: {r}")

if r and 'found' in r:
    try:
        info = json.loads(r)
        if info.get('found'):
            x, y = info['x'], info['y']
            print(f"  点击确定 ({x}, {y})...")
            mouse_click(sock, x, y)
            time.sleep(2)
    except:
        print("  点击失败")

print("\n[DONE] 封面设置完成")
sock.close()
