# -*- coding: utf-8 -*-
import sys, socket, json, time, base64, urllib.request, subprocess
sys.stdout.reconfigure(encoding='utf-8')

HOST = "localhost"
PORT = 9222

# ── 获取编辑页面ID ────────────────────────────────────────────────────────────
def get_editor_page_id():
    pages = json.loads(urllib.request.urlopen(f'http://{HOST}:{PORT}/json').read())
    for p in pages:
        url = p.get('url', '')
        if 'appmsg' in url and 'action=edit' in url:
            return p['id']
    return None

PAGE_ID = get_editor_page_id()
if not PAGE_ID:
    print("[ERROR] 未找到公众号编辑页面，请先运行 cdp_new_article.py")
    sys.exit(1)
print(f"[OK] 找到编辑页面: {PAGE_ID}")

# ── WebSocket 连接（使用 cdp_fill3.py 同款稳定实现）────────────────────────
def ws_connect(page_id):
    import urllib.parse
    ws_url = f"ws://{HOST}:{PORT}/devtools/page/{page_id}"
    parsed = urllib.parse.urlparse(ws_url)
    sock = socket.create_connection((parsed.hostname, parsed.port or 80), timeout=15)
    key = 'dGhlIHNhbXBsZSBub25jZQ=='
    handshake = (
        f'GET {parsed.path} HTTP/1.1\r\n'
        f'Host: {parsed.hostname}:{parsed.port}\r\n'
        'Upgrade: websocket\r\nConnection: Upgrade\r\n'
        f'Sec-WebSocket-Key: {key}\r\nSec-WebSocket-Version: 13\r\n\r\n'
    )
    sock.send(handshake.encode())
    resp = b''
    while b'\r\n\r\n' not in resp:
        resp += sock.recv(4096)
    return sock

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

def recv_frame(sock):
    def rx(n):
        buf = b''
        while len(buf) < n:
            buf += sock.recv(n - len(buf))
        return buf
    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')

_msg_id = 0
def call(sock, expr, timeout=10):
    global _msg_id
    _msg_id += 1
    mid = _msg_id
    send_frame(sock, json.dumps({
        'id': mid,
        'method': 'Runtime.evaluate',
        'params': {'expression': expr, 'returnByValue': True}
    }))
    sock.settimeout(timeout)
    while True:
        raw = recv_frame(sock)
        obj = json.loads(raw)
        if obj.get('id') == mid:
            res = obj.get('result', {}).get('result', {})
            return res.get('value', res.get('description', ''))

def screenshot(sock, filename):
    import os
    global _msg_id
    _msg_id += 1
    mid = _msg_id
    send_frame(sock, json.dumps({
        'id': mid,
        'method': 'Page.captureScreenshot',
        'params': {'format': 'png'}
    }))
    sock.settimeout(15)
    while True:
        raw = recv_frame(sock)
        obj = json.loads(raw)
        if obj.get('id') == mid:
            data = obj.get('result', {}).get('data', '')
            if data:
                # 尝试删除已存在的文件
                try:
                    if os.path.exists(filename):
                        os.remove(filename)
                except:
                    pass
                try:
                    with open(filename, 'wb') as f:
                        f.write(base64.b64decode(data))
                    print(f"[截图] 已保存: {filename}")
                except Exception as e:
                    print(f"[截图] 保存失败（忽略）: {e}")
            else:
                print("[截图] 失败，无数据")
            return

# ── 连接 ─────────────────────────────────────────────────────────────────────
sock = ws_connect(PAGE_ID)
print("[OK] WebSocket 已连接")
time.sleep(1)

# ── Step 1: 列出页面上所有按钮，诊断用 ─────────────────────────────────────
print("\n[诊断] 列出页面所有可见按钮文字...")
r = call(sock, """
(function(){
    var result = [];
    var els = document.querySelectorAll('a, button, span, div');
    for(var el of els){
        var t = (el.innerText || '').trim();
        if(t && t.length < 20 && (
            t.includes('草稿') || t.includes('保存') || t.includes('发表') || t.includes('预览')
        )){
            var s = window.getComputedStyle(el);
            if(s.display !== 'none' && s.visibility !== 'hidden'){
                result.push(el.tagName + '[' + (el.className||'').substring(0,30) + ']: ' + t);
            }
        }
    }
    return result.slice(0,20).join(' | ');
})()
""")
print(f"[按钮列表] {r}")

# ── Step 2: 截图看当前状态 ──────────────────────────────────────────────────
screenshot(sock, "before_save.png")

# ── Step 3: 尝试点击"保存为草稿" ────────────────────────────────────────────
print("\n[Step 3] 等待3秒后点击'保存为草稿'...")
time.sleep(3)
r = call(sock, """
(function(){
    // 方法1：查找所有元素，精确匹配文字
    var all = document.querySelectorAll('*');
    for(var el of all){
        var t = (el.innerText || '').trim();
        if(t === '保存为草稿'){
            var s = window.getComputedStyle(el);
            if(s.display !== 'none'){
                el.click();
                return 'clicked: ' + el.tagName + ' class=' + el.className;
            }
        }
    }
    // 方法2：模糊匹配
    for(var el of all){
        var t = (el.innerText || '').trim();
        if(t.includes('保存为草稿') && el.children.length === 0){
            el.click();
            return 'clicked_fuzzy: ' + el.tagName;
        }
    }
    return '未找到保存为草稿按钮';
})()
""")
print(f"[点击结果] {r}")
time.sleep(20)  # 等待20秒，确保长文章/多图片完全保存

# ── Step 4: 验证保存结果 ────────────────────────────────────────────────────
print("\n[Step 4] 验证保存状态（等待最多15秒）...")
saved = False
for i in range(15):
    time.sleep(1)
    r = call(sock, """
(function(){
    // 检查"已保存"提示
    var els = document.querySelectorAll('*');
    for(var el of els){
        var t = (el.innerText || '').trim();
        if(t === '已保存' || t.includes('保存成功')){
            var s = window.getComputedStyle(el);
            if(s.display !== 'none'){
                return 'SAVED:' + t;
            }
        }
    }
    // 检查URL是否变化（保存后通常会带appmsgid参数）
    return 'url:' + window.location.href.substring(0, 120);
})()
    """)
    print(f"  第{i+1}秒: {r}")
    if r and ('SAVED' in str(r) or 'appmsgid' in str(r)):
        print("✅ 保存成功确认！")
        saved = True
        break

# ── Step 5: 截图留证 ────────────────────────────────────────────────────────
screenshot(sock, "after_save.png")

if not saved:
    print("\n⚠️  未检测到保存成功信号，请查看 after_save.png 截图确认当前状态")
else:
    print("\n✅ 草稿保存完成！")

sock.close()

# ── Step 6: 完成提示（不关闭Chrome）──────────────────────────────────────────
print("\n✅ 草稿保存完成！")
print("\n[提示] Chrome保持打开，您可以：")
print("  1. 在Chrome中检查文章内容")
print("  2. 手动点击'发表'按钮发布文章")
print("  3. 或手动关闭Chrome")
