// Badge Recalculation Console - HTML admin page
// Calls /api/workflow/badge-recalc-execute in serial batches
module.exports = {
    rest: {
        method: 'GET',
        fullPath: '/api/workflow/badge-recalc-console'
    },
    async handler(ctx) {
        const userSession = ctx.meta.user;

        // Check if user is admin
        if (!userSession || !userSession.is_space_admin) {
            ctx.meta.$statusCode = 403;
            ctx.meta.$responseType = 'text/html';
            return 'Forbidden: Admin access required';
        }

        // Detect environment
        const env = process.env.NODE_ENV || 'development';
        const isProduction = env === 'production';

        const html = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Badge 重算控制台</title>
    <script src="/unpkg/jquery@3.7.1/dist/jquery.min.js"></script>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            background: #f5f5f5;
            padding: 20px;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        header h1 { font-size: 28px; margin-bottom: 8px; }
        header .env-badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: bold;
            margin-top: 8px;
        }
        header .env-prod { background: #e53e3e; }
        header .env-test { background: #48bb78; }

        .content { padding: 30px; }

        .usage-guide {
            background: #ebf8ff;
            border: 1px solid #90cdf4;
            border-radius: 6px;
            padding: 20px 24px;
            margin-bottom: 24px;
            font-size: 14px;
            color: #2a4365;
            line-height: 1.7;
        }
        .usage-guide h4 {
            margin-bottom: 10px;
            font-size: 16px;
            color: #2b6cb0;
        }
        .usage-guide ol, .usage-guide ul {
            margin-left: 20px;
            margin-bottom: 8px;
        }
        .usage-guide li { margin-bottom: 4px; }
        .usage-guide .warn {
            color: #c05621;
            font-weight: 500;
        }

        .operation-panel {
            background: #f7fafc;
            padding: 24px;
            border-radius: 6px;
            margin-bottom: 20px;
        }
        .operation-panel h3 {
            color: #2d3748;
            margin-bottom: 16px;
            font-size: 18px;
        }
        .form-group {
            margin-bottom: 16px;
        }
        .form-group label {
            display: block;
            margin-bottom: 6px;
            color: #4a5568;
            font-weight: 500;
        }
        .form-group input[type="text"],
        .form-group input[type="number"] {
            width: 100%;
            padding: 10px;
            border: 1px solid #cbd5e0;
            border-radius: 4px;
            font-size: 14px;
        }
        .form-group input[type="checkbox"] {
            margin-right: 8px;
        }
        .form-group input[type="radio"] {
            margin-right: 6px;
        }
        .radio-group label {
            display: inline-block;
            margin-right: 20px;
            font-weight: normal;
        }

        .btn {
            padding: 12px 24px;
            border: none;
            border-radius: 6px;
            font-size: 15px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
            margin-right: 12px;
        }
        .btn-primary {
            background: #667eea;
            color: white;
        }
        .btn-primary:hover { background: #5a67d8; }
        .btn-danger {
            background: #f56565;
            color: white;
        }
        .btn-danger:hover { background: #e53e3e; }
        .btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .result-panel {
            margin-top: 24px;
            padding: 20px;
            border-radius: 6px;
            display: none;
        }
        .result-panel.success {
            background: #c6f6d5;
            border: 1px solid #9ae6b4;
            color: #22543d;
        }
        .result-panel.error {
            background: #fed7d7;
            border: 1px solid #fc8181;
            color: #742a2a;
        }
        .result-panel.info {
            background: #bee3f8;
            border: 1px solid #90cdf4;
            color: #2a4365;
        }
        .result-panel h4 {
            margin-bottom: 12px;
            font-size: 16px;
        }
        .result-panel pre {
            background: rgba(0,0,0,0.05);
            padding: 12px;
            border-radius: 4px;
            overflow-x: auto;
            font-size: 13px;
            max-height: 300px;
            overflow-y: auto;
        }

        .progress-bar-container {
            width: 100%;
            height: 24px;
            background: #e2e8f0;
            border-radius: 12px;
            overflow: hidden;
            margin-top: 12px;
            margin-bottom: 8px;
        }
        .progress-bar-fill {
            height: 100%;
            background: linear-gradient(90deg, #667eea, #764ba2);
            border-radius: 12px;
            transition: width 0.3s ease;
            width: 0%;
        }
        .progress-text {
            font-size: 14px;
            color: #4a5568;
            margin-bottom: 4px;
        }

        .diff-record {
            background: #fffff0;
            border-left: 4px solid #d69e2e;
            padding: 8px 12px;
            margin: 6px 0;
            border-radius: 0 4px 4px 0;
            font-size: 13px;
        }
        .modified-record {
            background: #f0fff4;
            border-left: 4px solid #38a169;
            padding: 8px 12px;
            margin: 6px 0;
            border-radius: 0 4px 4px 0;
            font-size: 13px;
        }

        .loading {
            display: inline-block;
            width: 16px;
            height: 16px;
            border: 3px solid rgba(255,255,255,.3);
            border-radius: 50%;
            border-top-color: #fff;
            animation: spin 1s ease-in-out infinite;
            margin-left: 8px;
        }
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        .pre-wrapper {
            position: relative;
        }
        .pre-wrapper pre {
            margin: 0;
        }
        .btn-copy {
            position: absolute;
            top: 4px;
            right: 4px;
            padding: 2px 8px;
            font-size: 12px;
            background: #edf2f7;
            border: 1px solid #cbd5e0;
            border-radius: 4px;
            cursor: pointer;
            color: #4a5568;
            z-index: 1;
        }
        .btn-copy:hover {
            background: #e2e8f0;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>Badge 重算控制台</h1>
            <p>Badge Recalculation Console</p>
            <span class="env-badge ${isProduction ? 'env-prod' : 'env-test'}">
                环境: ${isProduction ? 'PRODUCTION' : 'TEST/DEV'}
            </span>
        </header>

        <div class="content">
            <div class="usage-guide">
                <h4>📖 使用说明</h4>
                <p><strong>用途：</strong>重算用户的审批流角标（badge）数据，修复因并发、异常、流程分类解绑等原因导致的角标数值不准确。</p>
                <p><strong>背景：</strong>角标数值在日常使用中可能因并发、异常等原因产生偏差。系统在每次新审批单提交时会自动重算相关用户的角标，大部分偏差会自然修正。本工具用于主动检查和批量修正那些长期未被自动修正的记录（如低频用户、已转岗用户等）。建议定期 Dry Run 检查，按需执行实际修正。</p>
                <p><strong>建议操作步骤：</strong></p>
                <ol>
                    <li>保持 <strong>Dry Run</strong> 勾选，先执行检查，查看哪些用户的角标数据存在差异；</li>
                    <li>确认差异记录合理（对比 old / new 值）；</li>
                    <li>取消勾选 Dry Run，再次执行，实际写入修正后的角标数据。</li>
                </ol>
                <p><strong>注意事项：</strong></p>
                <ul>
                    <li>Dry Run 默认开启，<strong>不会修改任何数据</strong>，可放心执行；</li>
                    <li>取消 Dry Run 后才会实际写入 <code>steedos_keyvalues</code> 表；</li>
                    <li class="warn">批量重算会调用 <code>count_instance_tasks</code> 逐用户计算，对数据库有一定查询压力，建议在业务低峰期执行。</li>
                </ul>
            </div>

            <!-- Panel 1: Per-user recalculation -->
            <div class="operation-panel">
                <h3>👤 按用户重算</h3>
                <div class="form-group">
                    <label>User ID:</label>
                    <input type="text" id="user-id" placeholder="输入用户 ID">
                </div>
                <div class="form-group">
                    <label>
                        <input type="checkbox" id="user-dryrun" checked>
                        Dry Run（仅检查差异，不实际修改数据）
                    </label>
                </div>
                <button class="btn btn-primary" id="user-btn" onclick="executeUserRecalc()">
                    ▶ 执行重算
                </button>
                <div class="result-panel" id="user-result"></div>
            </div>

            <!-- Panel 2: Batch recalculation -->
            <div class="operation-panel">
                <h3>📦 批量重算（全量）</h3>
                <div class="form-group" style="display:none;">
                    <label>范围选择:</label>
                    <input type="hidden" name="batch-scope" value="all">
                </div>
                <div class="form-group">
                    <label>每批用户数:</label>
                    <input type="number" id="batch-pagesize" value="50" min="1" max="200">
                </div>
                <div class="form-group">
                    <label>
                        <input type="checkbox" id="batch-dryrun" checked>
                        Dry Run（仅检查差异，不实际修改数据）
                    </label>
                </div>
                <button class="btn btn-primary" id="batch-start-btn" onclick="startBatch()">
                    ▶ 开始批量重算
                </button>
                <button class="btn btn-danger" id="batch-stop-btn" onclick="stopBatch()" disabled>
                    ⏹ 停止
                </button>
                <div id="batch-progress" style="display:none; margin-top: 16px;">
                    <div class="progress-text" id="batch-progress-text"></div>
                    <div class="progress-bar-container">
                        <div class="progress-bar-fill" id="batch-progress-bar"></div>
                    </div>
                </div>
                <div class="result-panel" id="batch-result"></div>
            </div>
        </div>
    </div>

    <script>
        function copyPreContent(btn) {
            var pre = btn.parentElement.querySelector('pre');
            if (!pre) return;
            navigator.clipboard.writeText(pre.textContent).then(function() {
                btn.textContent = '✅ 已复制';
                setTimeout(function() { btn.textContent = '📋 复制'; }, 1500);
            }).catch(function() {
                btn.textContent = '❌ 复制失败';
                setTimeout(function() { btn.textContent = '📋 复制'; }, 1500);
            });
        }
        // --- Per-user recalculation ---
        function executeUserRecalc() {
            var userId = $('#user-id').val().trim();
            if (!userId) { alert('请输入 User ID'); return; }

            var dryRun = $('#user-dryrun').is(':checked');
            var $btn = $('#user-btn');
            var $result = $('#user-result');

            $btn.prop('disabled', true).text('⏳ 执行中...');
            $result.removeClass('success error info').hide();

            $.ajax({
                url: '/api/workflow/badge-recalc-execute',
                type: 'GET',
                data: { scope: 'user', userId: userId, dryRun: dryRun },
                success: function(data) {
                    $btn.prop('disabled', false).text('▶ 执行重算');
                    $result.addClass('success').show();
                    var html = '<h4>✅ 执行完成</h4>';
                    html += renderSinglePageResult(data, dryRun);
                    $result.html(html);
                },
                error: function(xhr) {
                    $btn.prop('disabled', false).text('▶ 执行重算');
                    $result.removeClass('success').addClass('error').show();
                    var errorMsg = xhr.responseJSON || xhr.responseText || '未知错误';
                    $result.html('<h4>❌ 操作失败</h4><div class="pre-wrapper"><button class="btn-copy" onclick="copyPreContent(this)">📋 复制</button><pre style="background:#f5f5f5;padding:10px;border-radius:4px">' + JSON.stringify(errorMsg, null, 2) + '</pre></div>');
                }
            });
        }

        // --- Batch recalculation ---
        var batchStopped = false;

        function startBatch() {
            var scope = 'all';
            var pageSize = parseInt($('#batch-pagesize').val()) || 50;
            var dryRun = $('#batch-dryrun').is(':checked');

            batchStopped = false;
            $('#batch-start-btn').prop('disabled', true).text('⏳ 执行中...');
            $('#batch-stop-btn').prop('disabled', false);
            $('#batch-progress').show();
            $('#batch-progress-text').text('正在启动...');
            $('#batch-progress-bar').css('width', '0%');
            $('#batch-result').removeClass('success error info').hide().empty();

            runBatch(scope, pageSize, dryRun);
        }

        function stopBatch() {
            batchStopped = true;
            $('#batch-stop-btn').prop('disabled', true).text('正在停止...');
        }

        async function runBatch(scope, pageSize, dryRun) {
            var page = 1;
            var totalPages = 1;
            var totalUsers = 0;
            var processedUsers = 0;
            var diffUserIds = {};  // track unique userIds with hasDiff
            var diffResults = [];  // only keep diff records (not all results)
            var startTime = Date.now();
            var $result = $('#batch-result');

            try {
                while (page <= totalPages && !batchStopped) {
                    var params = { scope: scope, page: page, pageSize: pageSize, dryRun: dryRun };

                    var data = await $.ajax({
                        url: '/api/workflow/badge-recalc-execute',
                        type: 'GET',
                        data: params
                    });

                    totalPages = data.totalPages || 1;
                    totalUsers = data.totalUsers || 0;
                    processedUsers += (data.processedUsers || 0);

                    if (data.results && data.results.length) {
                        data.results.forEach(function(r) {
                            if (r.hasDiff) {
                                diffResults.push(r);
                                if (r.userId) diffUserIds[r.userId] = true;
                            }
                        });
                    }

                    // Update progress
                    var elapsedSec = Math.floor((Date.now() - startTime) / 1000);
                    var elapsedMin = Math.floor(elapsedSec / 60);
                    var elapsedRemSec = elapsedSec % 60;
                    var pct = totalPages > 0 ? Math.min(Math.round(page / totalPages * 100), 100) : 0;
                    $('#batch-progress-bar').css('width', pct + '%');
                    var diffUserCount = Object.keys(diffUserIds).length;
                    var diffRecordCount = diffResults.length;
                    $('#batch-progress-text').text(
                        '已处理 ' + Math.min(processedUsers, totalUsers) + ' / ' + totalUsers + ' 用户' +
                        '（第 ' + page + ' 页 / 共 ' + totalPages + ' 页）' +
                        '耗时 ' + elapsedMin + ' 分 ' + elapsedRemSec + ' 秒' +
                        ' | 找到差异用户: ' + diffUserCount + '（差异记录 ' + diffRecordCount + ' 条）'
                    );

                    page++;
                }

                // Finished
                $('#batch-start-btn').prop('disabled', false).text('▶ 开始批量重算');
                $('#batch-stop-btn').prop('disabled', true).text('⏹ 停止');

                var summary = { processedUsers: processedUsers, totalUsers: totalUsers, diffUserCount: Object.keys(diffUserIds).length, diffResults: diffResults, dryRun: dryRun, startTime: startTime };
                _lastDiffResults = diffResults;

                if (batchStopped) {
                    $result.addClass('info').show();
                    $result.html('<h4>⏹ 已手动停止</h4>' + renderBatchSummary(summary));
                } else {
                    $('#batch-progress-bar').css('width', '100%');
                    $result.addClass('success').show();
                    $result.html('<h4>✅ 批量重算完成</h4>' + renderBatchSummary(summary));
                }
            } catch (err) {
                $('#batch-start-btn').prop('disabled', false).text('▶ 开始批量重算');
                $('#batch-stop-btn').prop('disabled', true).text('⏹ 停止');

                var errorMsg = (err && err.responseJSON) || (err && err.responseText) || '未知错误';
                var summary = { processedUsers: processedUsers, totalUsers: totalUsers, diffUserCount: Object.keys(diffUserIds).length, diffResults: diffResults, dryRun: dryRun, startTime: startTime };
                _lastDiffResults = diffResults;
                $result.addClass('error').show();
                $result.html('<h4>❌ 批量重算失败（第 ' + (page) + ' 页时出错）</h4>' +
                    '<div class="pre-wrapper"><button class="btn-copy" onclick="copyPreContent(this)">📋 复制</button><pre style="background:#f5f5f5;padding:10px;border-radius:4px">' + JSON.stringify(errorMsg, null, 2) + '</pre></div>' +
                    renderBatchSummary(summary));
            }
        }

        // --- Result rendering helpers ---
        function renderSinglePageResult(data, dryRun) {
            var html = '';
            if (data.results && data.results.length) {
                var diffCount = 0;
                data.results.forEach(function(r) {
                    if (r.hasDiff) diffCount++;
                });
                html += '<p>处理用户数: <strong>' + (data.processedUsers || 1) + '</strong>';
                if (dryRun) html += ' | 有差异: <strong style="color:#d69e2e;">' + diffCount + '</strong>';
                else html += ' | 已修改: <strong style="color:#38a169;">' + diffCount + '</strong>';
                html += '</p>';
                html += renderResultRecords(data.results, dryRun);
            } else {
                html += '<p>无处理结果</p>';
            }
            html += '<details style="margin-top:15px"><summary>▼ 展开完整 JSON</summary><div class="pre-wrapper"><button class="btn-copy" onclick="copyPreContent(this)">📋 复制</button><pre style="max-height:300px;overflow:auto;background:#f5f5f5;padding:10px;border-radius:4px">' + JSON.stringify(data, null, 2) + '</pre></div></details>';
            return html;
        }

        function renderBatchSummary(summary) {
            var elapsed = Math.floor((Date.now() - summary.startTime) / 1000);
            var mins = Math.floor(elapsed / 60);
            var secs = elapsed % 60;
            var dryRun = summary.dryRun;
            var diffResults = summary.diffResults || [];
            var diffUserCount = summary.diffUserCount || 0;
            var MAX_DISPLAY = 100;

            var html = '<hr style="margin:10px 0;">';
            html += '<p>处理用户数: <strong>' + summary.processedUsers + '</strong> / ' + summary.totalUsers + ' | 耗时: <strong>' + mins + '分' + secs + '秒</strong></p>';

            if (diffUserCount > 0) {
                html += '<p>' + (dryRun ? '有差异用户' : '已修改用户') + ': <strong style="color:' + (dryRun ? '#d69e2e' : '#38a169') + ';">' + diffUserCount + '</strong>';
                html += '（差异记录 ' + diffResults.length + ' 条）</p>';
                var displayRecords = diffResults.slice(0, MAX_DISPLAY);
                html += renderResultRecords(displayRecords, dryRun);
                if (diffResults.length > MAX_DISPLAY) {
                    html += '<p style="color:#718096;font-size:13px;margin-top:8px;">⚠️ 仅显示前 ' + MAX_DISPLAY + ' 条差异记录（共 ' + diffResults.length + ' 条），请使用下方导出按钮查看完整数据。</p>';
                }
                html += '<div style="margin-top:12px;"><button class="btn btn-primary" onclick="exportDiffJson()" style="font-size:13px;padding:8px 16px;">📥 导出差异记录 JSON</button></div>';
            } else {
                html += '<p>所有用户均无差异 ✅</p>';
            }
            return html;
        }

        // Store diff results for export
        var _lastDiffResults = [];

        function exportDiffJson() {
            if (!_lastDiffResults.length) { alert('无差异记录可导出'); return; }
            var json = JSON.stringify(_lastDiffResults, null, 2);
            var blob = new Blob([json], { type: 'application/json' });
            var url = URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.download = 'badge-diff-' + new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-') + '.json';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }

        function escapeHtml(str) {
            if (!str) return '';
            return String(str).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
        }

        function renderResultRecords(records, dryRun) {
            var html = '';
            records.forEach(function(r) {
                if (r.hasDiff) {
                    var cls = dryRun ? 'diff-record' : 'modified-record';
                    var icon = dryRun ? '⚠️' : '✅';
                    var hint = dryRun ? '（Dry Run 未写入）' : '（已写入）';
                    var userLabel = r.userName
                        ? escapeHtml(r.userName) + '(' + escapeHtml((r.userId || '').substring(0, 8)) + ')'
                        : escapeHtml(r.userId || '-');
                    var spaceLabel = r.spaceName
                        ? escapeHtml(r.spaceName) + '(' + escapeHtml((r.space || '').substring(0, 8)) + ')'
                        : escapeHtml(r.space || '-');
                    html += '<div class="' + cls + '">' + icon + ' 用户: ' + userLabel + ' 工作区: ' + spaceLabel + ' ' + hint +
                        '<details><summary>详情</summary><div class="pre-wrapper"><button class="btn-copy" onclick="copyPreContent(this)">📋 复制</button><pre>' + escapeHtml(JSON.stringify(r, null, 2)) + '</pre></div></details></div>';
                }
            });
            return html;
        }
    </script>
</body>
</html>
        `;

        // Set response type to HTML
        ctx.meta.$responseType = 'text/html';
        return html;
    }
};
