#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""微信绑定二维码值守：轮询 → 过期自动重拉并推送到飞书 → 确认后落账号文件
用法：venv/bin/python 脚本/weixin_qr_watch.py
不打印 token（只打印长度/账号标识）。推送用 hermes send。
"""
import asyncio, sys, os, json, subprocess, time

REPO = os.path.expanduser('~/.hermes/hermes-agent')
ROOT = os.path.expanduser('~/Desktop/Hermes输出-工作类')
sys.path.insert(0, REPO)
HERMES_HOME = os.path.expanduser('~/.hermes')
QR_DIR = os.path.join(ROOT, '工具')
MAX_REFRESH = 8


def render_qr(url: str, path: str) -> None:
    import qrcode
    qr = qrcode.QRCode(box_size=14, border=4, error_correction=qrcode.constants.ERROR_CORRECT_M)
    qr.add_data(url)
    qr.make(fit=True)
    qr.make_image(fill_color='black', back_color='white').save(path)


def push(text: str) -> None:
    """推送文本或 MEDIA:<路径> 到飞书（失败不影响主循环）"""
    try:
        subprocess.run(['hermes', 'send', '--to', 'feishu', text],
                       capture_output=True, timeout=90)
    except Exception as exc:
        print('push failed:', exc, flush=True)


async def main():
    from gateway.platforms.weixin import (_api_get, _new_session, save_weixin_account,
                                          _fetch_qr, EP_GET_QR_STATUS, ILINK_BASE_URL, QR_TIMEOUT_MS)
    refresh = 0
    base = ILINK_BASE_URL
    async with _new_session() as s:
        qr_token = qr_url = ''
        try:                                   # 复用 /tmp/wx_qr_url.txt 里已发出的那张，保证图与轮询同源
            _l = open('/tmp/wx_qr_url.txt', encoding='utf-8').read().split('\n')
            qr_url, qr_token = (_l[0] or '').strip(), (_l[1] if len(_l) > 1 else '').strip()
        except Exception:
            pass
        if not qr_token:
            qr_token, qr_url = await _fetch_qr(s, '3')
        if not qr_token:
            print('FETCH_FAILED'); return 2
        while True:
            stamp = time.strftime('%H%M%S')
            png = os.path.join(QR_DIR, '微信绑定二维码_%s.png' % stamp)
            render_qr(qr_url or qr_token, png)
            print('QR(%d) %s  生成于 %s  url=%s'
                  % (refresh, os.path.basename(png), time.strftime('%H:%M:%S'), qr_url), flush=True)
            if refresh == 0:
                pass                          # 首张由主回复随消息发出，无需重复推送
            else:
                push('🔁 上一张二维码已过期，这是**新的一张**（约 5 分钟内有效）：\nMEDIA:' + png)
            deadline = time.monotonic() + 300
            last = ''
            while time.monotonic() < deadline:
                try:
                    r = await _api_get(s, base_url=base,
                                       endpoint='%s?qrcode=%s' % (EP_GET_QR_STATUS, qr_token),
                                       timeout_ms=QR_TIMEOUT_MS)
                except Exception:
                    await asyncio.sleep(2); continue
                st = str(r.get('status') or 'wait')
                if st != last:
                    print('status:', st, flush=True); last = st
                if st == 'scaned':
                    push('👀 已扫码，请在微信里点「确认」')
                elif st == 'scaned_but_redirect' and r.get('redirect_host'):
                    base = 'https://' + str(r['redirect_host'])
                elif st == 'confirmed':
                    creds = {'account_id': str(r.get('ilink_bot_id') or ''),
                             'token': str(r.get('bot_token') or ''),
                             'base_url': str(r.get('baseurl') or ILINK_BASE_URL),
                             'user_id': str(r.get('ilink_user_id') or '')}
                    if not creds['account_id'] or not creds['token']:
                        print('CONFIRMED_BUT_INCOMPLETE'); push('⚠️ 扫码确认了但凭据不完整，需要重试'); return 3
                    save_weixin_account(HERMES_HOME, **creds)
                    json.dump({'account_id': creds['account_id'], 'user_id': creds['user_id'],
                               'base_url': creds['base_url']},
                              open('/tmp/wx_bind_result.json', 'w', encoding='utf-8'), ensure_ascii=False)
                    print('CONFIRMED account_id=%s user_id=%s token_len=%d'
                          % (creds['account_id'], creds['user_id'], len(creds['token'])), flush=True)
                    push('✅ 微信扫码已确认\naccount_id: %s\nuser_id: %s\n下一步：把 account_id/token 写入 .env 并重启网关即可生效（等你点头）'
                         % (creds['account_id'], creds['user_id']))
                    return 0
                elif st == 'expired':
                    break
                await asyncio.sleep(2)
            else:
                print('TIMEOUT_THIS_ROUND', flush=True)
                push('⏱ 二维码超时未扫码，值守结束。需要时说一声"重发二维码"。')
                return 5
            refresh += 1
            if refresh > MAX_REFRESH:
                print('MAX_REFRESH_REACHED', flush=True)
                push('⏱ 已连续补发 %d 张都没扫上，先停止值守。需要时说一声"重发二维码"。' % MAX_REFRESH)
                return 6
            qr_token, qr_url = await _fetch_qr(s, '3')
            print('refreshed ->', refresh, flush=True)


sys.exit(asyncio.run(main()))
