#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""为工作台 AI 助手 Tab 增加「一键复制对话内容」功能
- 顶部「📋 复制对话」：整段对话按 Markdown 复制（含导出时间/用户/条数）
- 每条消息右上角「📋」：复制单条（AI 回答复制 Markdown 原文，表格保留 | 结构）
- 兜底：飞书内置浏览器不支持自动复制时，弹出手动复制框（自动全选）
同时在 工具/index.html（正式）与 工具/app.html（测试页）双路径生效。
"""
import os, re, shutil, datetime

ROOT = os.path.expanduser('~/Desktop/Hermes输出-工作类/工具')
STAMP = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
FILES = ['index.html', 'app.html']

JS_BLOCK = r"""
/* ── 一键复制对话内容（2026-09-17 新增）────────────────────────
   ① 顶部「📋 复制对话」= 整段导出为 Markdown
   ② 每条消息右上「📋」= 复制单条（优先取 chatHistory 的 Markdown 原文，表格保留 | 结构）
   ③ 自动复制失败（飞书 webview 等非安全上下文）→ 弹手动复制框并自动全选
   数据来源：chatHistory（与「归档为经验」同一份，保证内容一致） */
function copyToClipboard(text, okMsg) {
  function done() { showToast(okMsg || '✅ 已复制'); }
  function fallback() {
    try {
      var ta = document.createElement('textarea');
      ta.value = text; ta.setAttribute('readonly', '');
      ta.style.cssText = 'position:fixed;left:-9999px;top:0;opacity:0';
      document.body.appendChild(ta);
      ta.select(); ta.setSelectionRange(0, ta.value.length);
      var ok = document.execCommand('copy');
      ta.remove();
      if (ok) { done(); } else { showCopyFallback(text); }
    } catch (e) { showCopyFallback(text); }
  }
  if (navigator.clipboard && navigator.clipboard.writeText && window.isSecureContext) {
    navigator.clipboard.writeText(text).then(done)['catch'](fallback);
  } else { fallback(); }
}

function showCopyFallback(text) {
  var old = document.getElementById('copyFallbackOverlay');
  if (old) old.remove();
  var ov = document.createElement('div');
  ov.id = 'copyFallbackOverlay';
  ov.style.cssText = 'position:fixed;inset:0;background:rgba(15,23,42,.55);z-index:99999;display:flex;align-items:center;justify-content:center;padding:16px';
  var box = document.createElement('div');
  box.style.cssText = 'background:#fff;border-radius:12px;padding:16px;width:680px;max-width:94vw;max-height:86vh;display:flex;flex-direction:column;box-shadow:0 12px 40px rgba(0,0,0,.3)';
  var head = document.createElement('div');
  head.innerHTML = '<div style="font-weight:800;font-size:15px;margin-bottom:4px">📋 手动复制</div>' +
    '<div style="font-size:12px;color:#8a94a6;margin-bottom:8px">当前环境不支持自动复制，请点击下面文本框后按 ⌘C / Ctrl+C</div>';
  box.appendChild(head);
  var ta = document.createElement('textarea');
  ta.style.cssText = 'flex:1;min-height:300px;font-size:12px;line-height:1.6;padding:10px;border:1px solid #dbe3ee;border-radius:8px;font-family:inherit;resize:vertical';
  ta.value = text;
  box.appendChild(ta);
  var bar = document.createElement('div');
  bar.style.cssText = 'text-align:right;margin-top:10px';
  var btn = document.createElement('button');
  btn.type = 'button';
  btn.textContent = '关闭';
  btn.style.cssText = 'background:#1852B6;color:#fff;border:none;border-radius:8px;padding:8px 18px;font-size:13px;font-weight:700;cursor:pointer';
  btn.onclick = function () { ov.remove(); };
  bar.appendChild(btn); box.appendChild(bar);
  ov.appendChild(box);
  ov.addEventListener('click', function (e) { if (e.target === ov) ov.remove(); });
  document.body.appendChild(ov);
  ta.focus(); ta.select();
}

function chatToMarkdown() {
  var u = state.user || {};
  var out = [];
  out.push('# AI 助手对话记录');
  out.push('');
  out.push('- 导出时间：' + new Date().toLocaleString('zh-CN'));
  if (u.name) out.push('- 用户：' + u.name + (u.dept ? '（' + u.dept + '）' : ''));
  out.push('- 消息数：' + chatHistory.length);
  out.push('');
  out.push('---');
  out.push('');
  for (var i = 0; i < chatHistory.length; i++) {
    var m = chatHistory[i];
    out.push('**' + (m.role === 'user' ? '👤 我' : '🤖 AI 助手') + '：**');
    out.push('');
    out.push(String(m.content == null ? '' : m.content).trim());
    out.push('');
  }
  return out.join('\n');
}

function copyChatAll(btn) {
  if (!chatHistory || !chatHistory.length) { showToast('⚠️ 当前对话为空，暂无可复制内容'); return; }
  var text = chatToMarkdown();
  copyToClipboard(text, '✅ 已复制 ' + chatHistory.length + ' 条对话（' + text.length + ' 字）');
  if (btn) {
    var oldTxt = btn.textContent;
    btn.textContent = '✅ 已复制';
    setTimeout(function () { btn.textContent = oldTxt; }, 1600);
  }
}

function copyMsg(btn) {
  var el = (btn && btn.closest) ? btn.closest('.chat-msg') : null;
  if (!el) return;
  var mi = parseInt(el.getAttribute('data-mi'), 10);
  var txt = (!isNaN(mi) && chatHistory[mi] && chatHistory[mi].content != null) ? chatHistory[mi].content : '';
  if (!txt) {   // 退回渲染文本（克隆后剔除复制按钮，避免把 📋 也复制进去）
    var clone = el.cloneNode(true);
    var cb = clone.querySelector('.msg-copy');
    if (cb) cb.remove();
    txt = clone.innerText || clone.textContent || '';
  }
  txt = String(txt).trim();
  if (!txt) { showToast('⚠️ 该条内容为空'); return; }
  copyToClipboard(txt, '✅ 已复制这条内容（' + txt.length + ' 字）');
  btn.textContent = '✅';
  setTimeout(function () { btn.textContent = '📋'; }, 1400);
}

function decorateChatMsgs() {
  var body = document.getElementById('aiChatBody');
  if (!body) return;
  var msgs = body.querySelectorAll('.chat-msg');
  var hi = 0;
  for (var i = 0; i < msgs.length; i++) {
    var el = msgs[i];
    if (el.querySelector('.chat-typing')) continue;
    if (chatHistory[hi] && ((chatHistory[hi].role === 'user') === el.classList.contains('user'))) {
      el.setAttribute('data-mi', hi); hi++;
    }
    if (!el.querySelector('.msg-copy')) {
      var b = document.createElement('button');
      b.type = 'button';
      b.className = 'msg-copy';
      b.title = '复制这条内容';
      b.textContent = '📋';
      b.onclick = (function (bb) { return function (ev) { ev.stopPropagation(); copyMsg(bb); }; })(b);
      el.appendChild(b);
    }
  }
}

"""

CSS_BLOCK = """
/* 一键复制对话：消息右上角按钮（触屏无 hover，故常显但低干扰） */
.chat-msg{position:relative}
.msg-copy{position:absolute;top:5px;right:5px;width:22px;height:22px;padding:0;border:1px solid #dbe3ee;border-radius:6px;background:#fff;color:#5b7089;font-size:11px;line-height:1;cursor:pointer;opacity:.5;z-index:2;font-family:inherit}
.msg-copy:hover{opacity:1;border-color:#1852B6;color:#1852B6}
.chat-msg.user .msg-copy{background:rgba(255,255,255,.92);border-color:rgba(255,255,255,.55);color:#1852B6}
"""


def patch(path):
    src = open(path, encoding='utf-8').read()
    orig = src
    if 'function copyChatAll' in src:
        print('  ⏭  %s 已含该功能，跳过' % os.path.basename(path)); return False

    # ① CSS：接在 .chat-msg 基础样式之后
    m = re.search(r'^\.chat-msg\{[^\n]*\}\n', src, re.M)
    assert m, '未找到 .chat-msg 样式'
    src = src[:m.end()] + CSS_BLOCK + src[m.end():]

    # ② JS：插在 function newChat() 之前
    m2 = re.search(r'^function newChat\(\) \{', src, re.M)
    assert m2, '未找到 newChat'
    src = src[:m2.start()] + JS_BLOCK.strip() + '\n\n' + src[m2.start():]

    # ③ 顶部按钮：复制对话（放在「归档为经验」左侧，白色描边风格一致）
    anchor = '<div style="display:flex;gap:6px;flex-shrink:0"><button onclick="archiveExperience()"'
    assert anchor in src, '未找到 chat-head 按钮组'
    btn = ('<div style="display:flex;gap:6px;flex-shrink:0">'
           '<button onclick="copyChatAll(this)" style="background:rgba(255,255,255,.2);color:#fff;'
           'border:none;border-radius:14px;padding:5px 12px;font-size:11px;font-weight:700;cursor:pointer;'
           'white-space:nowrap;width:auto;height:26px" title="把整段对话复制为 Markdown">📋 复制对话</button>'
           '<button onclick="archiveExperience()"')
    src = src.replace(anchor, btn, 1)

    # ④ renderAiAssistant 末尾：渲染完历史后装饰消息
    a4 = "  var b = document.getElementById('aiChatBody');\n  if (b) b.scrollTop = b.scrollHeight;\n}"
    assert a4 in src, '未找到 renderAiAssistant 末尾'
    src = src.replace(a4, "  var b = document.getElementById('aiChatBody');\n  if (b) b.scrollTop = b.scrollHeight;\n"
                          "  decorateChatMsgs();\n}", 1)

    # ⑤ appendChatMsg 末尾：新消息即时加复制按钮
    a5 = "  body.appendChild(div);\n  body.scrollTop = body.scrollHeight;\n  return div;\n}"
    assert a5 in src, '未找到 appendChatMsg 末尾'
    src = src.replace(a5, "  body.appendChild(div);\n  body.scrollTop = body.scrollHeight;\n"
                          "  decorateChatMsgs();\n  return div;\n}", 1)

    # ⑥ 流式结束填充正文后，重新装饰（拿到最终内容的索引）
    a6 = "      if (md) md.innerHTML = mdRender(cleanText || fullText);"
    assert a6 in src, '未找到流式收尾'
    src = src.replace(a6, a6 + "\n      decorateChatMsgs();", 1)

    shutil.copy2(path, path + '.bak_copy_' + STAMP)
    open(path, 'w', encoding='utf-8').write(src)
    print('  ✅ %-12s %d → %d 字节（+%d）｜备份 .bak_copy_%s'
          % (os.path.basename(path), len(orig), len(src), len(src) - len(orig), STAMP))
    return True


if __name__ == '__main__':
    for f in FILES:
        p = os.path.join(ROOT, f)
        if os.path.exists(p):
            patch(p)
        else:
            print('  ⚠️  %s 不存在' % f)
