#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""把工作台外壳与活动录入页部署到 CloudBase 静态托管，并回读校验。

先下载线上现有副本做回滚快照，再逐个部署，最后回读比 md5。
"""
import hashlib
import io
import os
import ssl
import subprocess
import sys
import time
import urllib.parse
import urllib.request

CDN = 'https://bier-sales-d0gatbvlx288724e9-1458438710.tcloudbaseapp.com'
ROOT = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
TCB = '/Users/liuxinyuan/.npm-global/bin/tcb'
ENV = 'bier-sales-d0gatbvlx288724e9'
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

PAIRS = [
    ('工具/index.html', '/workbench/index.html'),
    ('工具/app.html', '/workbench/app.html'),
    ('工具/活动录入.html', '/工具/活动录入.html'),
    ('工具/客户拉通大表_demo_v11_活动录入V2同步_20261101_V01.html', '/工具/客户拉通大表_demo_v11_活动录入V2同步_20261101_V01.html'),
    ('工具/飞书活动商机关联.html', '/工具/飞书活动商机关联.html'),
    ('工具/销售管理后台.html', '/工具/销售管理后台.html'),
    ('工具/销售管理后台.html', '/admin/index.html'),
]

apply = '--apply' in sys.argv
ts = time.strftime('%Y%m%d-%H%M%S')
BAK = os.path.join(ROOT, '_bak_cdn_%s' % ts)

print('工作台部署到 CDN —— %s\n' % ('APPLY' if apply else 'DRY-RUN'))


def fetch(url):
    r = urllib.request.urlopen(urllib.request.Request(url, headers={'User-Agent': 'probe'}),
                               timeout=25, context=ctx)
    return r.status, r.read()


def enc(p):
    return '/'.join(urllib.parse.quote(seg) for seg in p.split('/'))


# ① 回滚快照
if apply:
    os.makedirs(BAK, exist_ok=True)
    for lo, rp in PAIRS:
        try:
            st, b = fetch(CDN + enc(rp))
            name = rp.strip('/').replace('/', '__')
            io.open(os.path.join(BAK, name), 'wb').write(b)
            print('  快照 %-34s %7d 字节' % (rp, len(b)))
        except Exception as e:
            print('  快照 %-34s 失败: %s' % (rp, str(e)[:50]))
    print('  快照目录 %s\n' % BAK)

# ② 部署
ok = True
for lo, rp in PAIRS:
    lb = io.open(os.path.join(ROOT, lo), 'rb').read()
    lmd5 = hashlib.md5(lb).hexdigest()
    if not apply:
        print('  [干跑] %-22s → %-28s %7d 字节 md5=%s' % (lo, rp, len(lb), lmd5[:9]))
        continue
    r = subprocess.run([TCB, 'hosting', 'deploy', os.path.join(ROOT, lo), rp, '-e', ENV],
                       capture_output=True, text=True, timeout=300)
    good = r.returncode == 0
    if not good:
        ok = False
    print('  %s %-22s → %-28s %7d 字节 %s' % ('✅' if good else '❌', lo, rp, len(lb),
                                             (r.stdout or '')[-90:].replace('\n', ' ') if not good else ''))

if not apply:
    print('\n干跑结束，未部署。')
    sys.exit(0)
if not ok:
    print('\n有部署失败 → 终止校验')
    sys.exit(1)

# ③ 回读校验
print('\n=== 回读校验（本地 vs 线上 md5）===')
time.sleep(6)
allok = True
for lo, rp in PAIRS:
    lb = io.open(os.path.join(ROOT, lo), 'rb').read()
    lmd5 = hashlib.md5(lb).hexdigest()
    got = None
    for attempt in range(3):
        try:
            st, rb = fetch(CDN + enc(rp) + '?cb=%d' % (int(time.time()) + attempt))
            if hashlib.md5(rb).hexdigest() == lmd5:
                got = (st, rb, attempt)
                break
            if got is None:
                got = (st, rb, attempt)
        except Exception as e:
            print('  取回失败 %s: %s' % (rp, str(e)[:50]))
        time.sleep(5)
    if got and hashlib.md5(got[1]).hexdigest() == lmd5:
        print('  ✅ %-22s 一致 (%7d 字节 md5=%s)' % (lo, len(got[1]), lmd5[:9]))
    else:
        allok = False
        print('  ❌ %-22s 不一致：线上 md5=%s 本地=%s'
              % (lo, hashlib.md5(got[1]).hexdigest()[:9] if got else '取不到', lmd5[:9]))

# 关键标记
print()
for lo, rp, kw in [('工具/index.html', '/workbench/index.html', 'visitStats'),
                   ('工具/app.html', '/workbench/app.html', 'visitStats'),
                   ('工具/活动录入.html', '/工具/活动录入.html', 'ACT_V2_PROD'),
                   ('工具/客户拉通大表_demo_v11_活动录入V2同步_20261101_V01.html', '/工具/客户拉通大表_demo_v11_活动录入V2同步_20261101_V01.html', '客户拉通大表 · V2 真实数据'),
                   ('工具/飞书活动商机关联.html', '/工具/飞书活动商机关联.html', '飞书活动 · 商机关联'),
                   ('工具/销售管理后台.html', '/工具/销售管理后台.html', '宝锐销售管理后台'),
                   ('工具/销售管理后台.html', '/admin/index.html', '宝锐销售管理后台')]:
    try:
        st, rb = fetch(CDN + enc(rp))
        print('  %-22s 线上含 %-10s %s' % (lo, kw, '✅' if kw.encode() in rb else '❌'))
    except Exception as e:
        print('  %-22s 取回失败 %s' % (lo, str(e)[:40]))

print('\n%s' % ('✅ 部署并校验通过' if allok else '❌ 校验未通过'))
sys.exit(0 if allok else 1)
