#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
报销 Tab 加「用自己的邮箱自动抓票」（EXPENSE_MAIL_V1）
  · 可折叠面板：邮箱账号 + IMAP 授权码 → 保存 → 立即抓取
  · 强调隔离：只抓本人邮箱、只进本人工作区
双文件：工具/index.html、工具/app.html
"""
import re, subprocess, tempfile, os, sys

CSS_ANCHOR = "/* 使用流程指南（EXPENSE_GUIDE_V1） */"
CSS_NEW = """/* 用自己邮箱抓票（EXPENSE_MAIL_V1） */
.eg-mailrow{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:6px 0 8px}
.eg-mailrow input{flex:1 1 210px;min-width:150px;padding:8px 10px;border:1px solid #cfdcee;border-radius:8px;font-size:13px;box-sizing:border-box}
.eg-tips{margin:8px 0 0;padding-left:18px;line-height:1.8;font-size:12.5px;color:#44506a}
.eg-tips li{margin-bottom:3px}
""" + CSS_ANCHOR

# ── HTML：插在上传框之后 ──
HTML_ANCHOR = "'<input type=\"file\" id=\"expFile\" multiple accept=\".pdf,.zip,.ofd,.png,.jpg,.jpeg\" style=\"display:none\">' +"
HTML_NEW = HTML_ANCHOR + """
    '<details class="exp-guide" id="expMail" ontoggle="if(this.open){expMailLoad();}">' +
      '<summary>\\u{1F4EE} 用自己的邮箱自动抓票（可选 · 点击展开）</summary>' +
      '<div class="eg-body">' +
        '<div class="eg-mailrow">' +
          '<input type="text" id="expMailAcct" placeholder="你的邮箱账号（如 123456@qq.com）" autocomplete="off">' +
          '<input type="password" id="expMailCode" placeholder="IMAP 授权码（不是邮箱登录密码）" autocomplete="new-password">' +
          '<button class="exp-btn pri" onclick="expMailSave()">保存</button>' +
          '<button class="exp-btn" onclick="expMailFetch()">立即抓取</button>' +
        '</div>' +
        '<div class="exp-note" id="expMailStat">展开后自动检查配置…</div>' +
        '<ul class="eg-tips">' +
          '<li><b>只抓你自己的邮箱</b>：票只进你自己的工作区，别人的票你看不到，你的票别人也看不到（含管理员）。</li>' +
          '<li>QQ 邮箱：设置 → 账户 → 开启 IMAP 服务 → 生成<b>授权码</b>（16 位），填到上面的授权码框。</li>' +
          '<li>保存后点「立即抓取」：拉取最近 7 天邮件里的 PDF / ZIP 发票（打车、ETC 的 ZIP 会自动解包），自动解析 + 校验，完成飞书通知你，可关页面。</li>' +
          '<li>不想配邮箱也行 —— 直接把发票拖到上面的上传区，效果一样。</li>' +
        '</ul>' +
      '</div></details>' +"""

# ── JS：插在 expReq 之后 ──
JS_ANCHOR = """function renderExpense(main) {"""
JS_NEW = """function expMailStat(msg) {
  var el = document.getElementById('expMailStat');
  if (el) el.textContent = msg;
}
function expMailLoad() {
  expMailStat('检查中…');
  expReq('/api/expense/mail').then(function(d) {
    if (!d.ok) { expMailStat('❌ ' + (d.error || '获取失败')); return; }
    var a = document.getElementById('expMailAcct');
    if (a && d.account && !a.value) a.value = d.account;
    expMailStat(d.configured
      ? ('✅ 已配置：' + d.account + '（' + (d.host || 'imap.qq.com') + '）' + (d.running ? ' ｜ 正在抓取中…' : ''))
      : 'ℹ️ 还没配置：填邮箱账号和 IMAP 授权码，点「保存」即可。');
  })['catch'](function(e) { expMailStat('❌ ' + (e && e.message ? e.message : '网络错误')); });
}
function expMailSave() {
  var a = (document.getElementById('expMailAcct') || {}).value || '';
  var c = (document.getElementById('expMailCode') || {}).value || '';
  if (!a || !c) { showToast('邮箱账号与授权码都要填'); return; }
  expMailStat('保存中…');
  expReq('/api/expense/mail', { method: 'POST', headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ '账号': a, '授权码': c }) }).then(function(d) {
    if (!d.ok) { expMailStat('❌ ' + (d.error || '保存失败')); return; }
    var ci = document.getElementById('expMailCode');
    if (ci) ci.value = '';
    expMailStat('✅ ' + (d.msg || '已保存') + ' ｜ 账号 ' + (d.account || ''));
    showToast('✅ 邮箱授权码已保存');
  })['catch'](function(e) { expMailStat('❌ ' + (e && e.message ? e.message : '网络错误')); });
}
function expMailFetch() {
  expMailStat('正在启动抓取…');
  expReq('/api/expense/mail/fetch', { method: 'POST' }).then(function(d) {
    if (!d.ok) { expMailStat('❌ ' + (d.error || '启动失败')); return; }
    expMailStat('⏳ ' + (d.msg || '已开始抓取') + '（完成后飞书通知你，可关页面）');
    showToast('⏳ 已开始抓取你的邮箱');
  })['catch'](function(e) { expMailStat('❌ ' + (e && e.message ? e.message : '网络错误')); });
}

""" + JS_ANCHOR


def patch(path):
    s = open(path, encoding='utf-8').read()
    if 'expMailLoad' in s:
        print('  ⏭️ %s 已含邮箱面板，跳过' % path)
        return True
    orig = len(s)
    assert CSS_ANCHOR in s, 'CSS 锚点未命中 ' + path
    s = s.replace(CSS_ANCHOR, CSS_NEW, 1)
    assert HTML_ANCHOR in s, 'HTML 锚点未命中 ' + path
    s = s.replace(HTML_ANCHOR, HTML_NEW, 1)
    assert JS_ANCHOR in s, 'JS 锚点未命中 ' + path
    s = s.replace(JS_ANCHOR, JS_NEW, 1)
    open(path, 'w', encoding='utf-8').write(s)
    js = '\n'.join(re.findall(r'<script>(.*?)</script>', s, re.S))
    p = tempfile.mktemp(suffix='.js')
    open(p, 'w', encoding='utf-8').write(js)
    r = subprocess.run(['node', '--check', p], capture_output=True, text=True)
    os.unlink(p)
    print('  %s %d → %d 字符 ｜ JS %s %s' % (path, orig, len(s), '✅' if r.returncode == 0 else '❌', r.stderr[:130] if r.returncode else ''))
    return r.returncode == 0


if __name__ == '__main__':
    ok = all(patch(f) for f in ('工具/index.html', '工具/app.html'))
    print('  结果:', '✅ 全部通过' if ok else '❌ 有失败')
    sys.exit(0 if ok else 1)
