#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""P2-P0：工作台导航重构（经营 / 客户 / 我的 / 智能）。

按用户 2026-10-07「都按建议」执行的 8 条决定：
  Q1 四域，我的=纯个人事务 ｜ Q3 我的活动下线 ｜ Q5 订单+成交价并为一个 Tab
  Q6 客诉移入经营 ｜ 目标/数据管理归入经营 ｜ Q7 移动端底栏改 4 项

两入口分别处理（app.html 是精简外壳：无 orderEntry / openActivityEntry / specialReq / dataMgmt）。
用「标记区间替换」而不是长字符串精确匹配，避免空白差异导致漏命中。
"""
import io
import os
import shutil
import sys
import time

ROOT = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'

INDEX_TABS = """var TABS = [
  /* ── 📊 经营管理（业务结果与过程）── */
  { id: 'dashboard', group: 'biz', label: '看板', icon: '📊', lines: ['da','ls'] },
  { id: 'visitStats', group: 'biz', label: '拜访与活动', icon: '📈', lines: ['da','ls'] },
  { id: 'orders', group: 'biz', label: '订单与业绩', icon: '📦', lines: ['da','ls'] },
  { id: 'complaints', group: 'biz', label: '客诉', icon: '🔴', lines: ['da'] },
  { id: 'targetsAdmin', group: 'biz', label: '目标基础数据', icon: '🎯', lines: ['da','ls'], adminOnly: true },
  { id: 'dataMgmt', group: 'biz', label: '数据管理', icon: '📤', lines: ['da','ls'], adminOnly: true },
  /* ── 👥 客户管理（客户资产，不做过程统计）── */
  { id: 'customers', group: 'cust', label: '客户', icon: '📋', lines: ['da'] },
  { id: 'groups', group: 'cust', label: '课题组', icon: '🔬', lines: ['ls'] },
  { id: 'oppSandbox', group: 'cust', label: '商机沙盘', icon: '🎯', lines: ['da'] },
  { id: 'visitPrep', group: 'cust', label: '访前准备', icon: '📝', lines: ['da','ls'] },
  { id: 'specialReq', group: 'cust', label: '特殊要求', icon: '⭐', lines: ['da','ls'] },
  /* ── 🧑‍💼 我的（只放个人事务）── */
  { id: 'todos', group: 'mine', label: '待办', icon: '✅', lines: ['da','ls'] },
  { id: 'expense', group: 'mine', label: '报销', icon: '🧾', lines: ['da','ls'] },
  /* ── 🤖 智能 ── */
  { id: 'aiAssistant', group: 'ai', label: 'AI 助手', icon: '🤖', lines: ['da','ls'] }
  /* 2026-10-07 结构重构：下线「我的活动」(冗余) /「活动录入」(并入拜访与活动) /
     「历史成交价」(降为订单与业绩二级视图) /「岗前培训」(早已隐藏)。
     恢复方式见本仓 _bak_p2_nav_* 备份。 */
];"""

APP_TABS = """var TABS = [
  /* ── 📊 经营管理 ── */
  { id: 'dashboard', group: 'biz', label: '看板', icon: '📊', lines: ['da','ls'] },
  { id: 'visitStats', group: 'biz', label: '拜访与活动', icon: '📈', lines: ['da','ls'] },
  { id: 'orders', group: 'biz', label: '订单与业绩', icon: '📦', lines: ['da','ls'] },
  { id: 'complaints', group: 'biz', label: '客诉', icon: '🔴', lines: ['da'] },
  { id: 'targetsAdmin', group: 'biz', label: '目标基础数据', icon: '🎯', lines: ['da','ls'], adminOnly: true },
  /* ── 👥 客户管理 ── */
  { id: 'customers', group: 'cust', label: '客户', icon: '📋', lines: ['da'] },
  { id: 'groups', group: 'cust', label: '课题组', icon: '🔬', lines: ['ls'] },
  { id: 'oppSandbox', group: 'cust', label: '商机沙盘', icon: '🎯', lines: ['da'] },
  { id: 'visitPrep', group: 'cust', label: '访前准备', icon: '📝', lines: ['da','ls'] },
  /* ── 🧑‍💼 我的 ── */
  { id: 'todos', group: 'mine', label: '待办', icon: '✅', lines: ['da','ls'] },
  { id: 'expense', group: 'mine', label: '报销', icon: '🧾', lines: ['da','ls'] },
  /* ── 🤖 智能 ── */
  { id: 'aiAssistant', group: 'ai', label: 'AI 助手', icon: '🤖', lines: ['da','ls'] }
];"""

GRP_NEW = "var _grp = [['biz', '📊 经营管理'], ['cust', '👥 客户管理'], ['mine', '🧑‍💼 我的'], ['ai', '🤖 智能']];"
KEEP_NEW = "var _keep = ['visitStats', 'customers', 'todos', 'aiAssistant'];"

OPEN_ACT_NEW = """function openActivityEntry(customerName) {
  /* 2026-10-07 结构重构：统一到「拜访与活动」的「录」态。
     原先指向的工具/宝锐活动录入.html 是 MVP 老页（只生成文本、不提交活动、无活动形式/关联订单/待办确认），
     从拜访卡记的拜访因此从未进入工作台统计。现在统一走 工具/活动录入.html。 */
  try { sessionStorage.removeItem('bior_draft_ack_v1'); } catch(e){}
  visitHubState = 'rec';
  visitHubCustomer = customerName || '';
  switchTab('visitStats');
}"""

ORDER_HUB = """var ordHubView = 'orders';
function renderOrderHub(main) {
  main.innerHTML = '<div class="card" style="padding:14px 16px 4px"><div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">' +
    '<button class="btn btn-sm ' + (ordHubView === 'orders' ? 'active' : '') + '" onclick="ordHubView=\\'orders\\';render()">📦 订单管理</button>' +
    '<button class="btn btn-sm ' + (ordHubView === 'price' ? 'active' : '') + '" onclick="ordHubView=\\'price\\';render()">💰 历史成交价</button>' +
    '<span class="text-muted" style="font-size:12px">同一件事的两个视角：查单 / 查价</span>' +
    '</div></div><div id="ordHubBody"></div>';
  var body = document.getElementById('ordHubBody');
  if (!body) return;
  if (ordHubView === 'price') renderOrderEntry(body); else renderOrders(body);
}

"""

PAIRS_INDEX = [
    ('TABS 区间', 'var TABS = [', '\n];', INDEX_TABS),
    ('_grp 分组名', 'var _grp = [[', '];', GRP_NEW),
    ('_keep 底栏', 'var _keep = [', '];', KEEP_NEW),
    ('openActivityEntry', 'function openActivityEntry(customerName) {',
     '\n\n/* ---------- 测试报告定向收集（2026-09-15 新增 · 2026-10-07 整 Tab 下线）',
     OPEN_ACT_NEW),
    ('订单 hub 函数', '/* ---------- 拜访视图（P1）：当月线下拜访次数 / 线上跟进次数 ---------- */',
     None, ORDER_HUB + '/* ---------- 拜访视图（P1）：当月线下拜访次数 / 线上跟进次数 ---------- */'),
    ('分发器 orders→hub', "case 'orders': renderOrders(main); break;", None,
     "case 'orders': renderOrderHub(main); break;"),
    ('访前准备返回链', '查看「我的活动」Tab 或飞书项目中的历史拜访记录', None, '查看「拜访与活动」或飞书项目中的历史拜访记录'),
    ('访前准备返回按钮', "onclick=\"switchTab(\\'myActivities\\');return false\" class=\"btn btn-sm\">我的活动</a>", None,
     "onclick=\"switchTab(\\'visitStats\\');return false\" class=\"btn btn-sm\">拜访与活动</a>"),
]

PAIRS_APP = [
    ('TABS 区间', 'var TABS = [', '\n];', APP_TABS),
    ('_grp 分组名', 'var _grp = [[', '];', GRP_NEW),
    ('_keep 底栏', 'var _keep = [', '];', KEEP_NEW),
]


def apply_file(f, pairs, apply, bak, log):
    s = io.open(f, encoding='utf-8').read()
    if apply:
        os.makedirs(bak, exist_ok=True)
        shutil.copy2(f, os.path.join(bak, os.path.basename(f)))
    ok = True
    for label, start, end, new in pairs:
        i = s.find(start)
        if i < 0:
            print('  ❌ %-22s 未找到起点' % label)
            ok = False
            continue
        if end is None:          # 等长替换
            n = s.count(start)
            s = s.replace(start, new, 1)
            print('  ✅ %-22s 替换 %d 处（命中 %d）' % (label, 1, n))
            continue
        j = s.find(end, i + len(start))
        if j < 0:
            print('  ❌ %-22s 未找到终点' % label)
            ok = False
            continue
        old_len = j + len(end) - i
        s = s[:i] + new + s[j + len(end):]
        print('  ✅ %-22s 替换 %d 字符' % (label, old_len))
    if ok and apply:
        io.open(f, 'w', encoding='utf-8').write(s)
    return ok, s


def main():
    apply = '--apply' in sys.argv
    ts = time.strftime('%Y%m%d-%H%M%S')
    bak = os.path.join(ROOT, '_bak_p2_nav_%s' % ts)
    print('P2-P0 导航重构 —— %s\n' % ('APPLY' if apply else 'DRY-RUN'))
    allok = True
    for name, pairs in [('工具/index.html', PAIRS_INDEX), ('工具/app.html', PAIRS_APP)]:
        print('=== %s ===' % name)
        ok, s = apply_file(os.path.join(ROOT, name), pairs, apply, bak, None)
        allok = allok and ok
        if ok:
            print('    Tab 数 %d ｜ 分组 %s'
                  % (s.count("group: 'biz'") + s.count("group: 'cust'") + s.count("group: 'mine'") + s.count("group: 'ai'"),
                     [g for g in ['biz', 'cust', 'mine', 'ai', 'other'] if ("['" + g + "',") in s]))
    if apply and allok:
        print('\n原文件备份 → %s' % bak)
    print('\n%s' % ('全部命中 ✅' if allok else '有未命中 ❌'))
    return 0 if allok else 1


sys.exit(main())
