/* ============================================================
   MetaLab 共享工具函数 — 前后台公用，消除 DRY 重复
   ============================================================ */
'use strict';

/**
 * 获取 CSRF 令牌 — 优先从 cookie 读取（与服务端验证源一致，token 刷新后保持最新），
 * meta 标签作为后备（部分页面可能未设置 cookie）
 * @returns {string} CSRF 令牌，未找到时返回空字符串
 */
function getCSRFToken() {
    var match = document.cookie.match(/(?:^|;\s*)mlb_csrf=([^;]*)/);
    if (match && match[1]) return match[1];
    var meta = document.querySelector('meta[name="csrf-token"]');
    return meta ? meta.getAttribute('content') : '';
}

/**
 * HTML 转义 — 使用 DOM API 安全转义，避免 XSS
 * @param {string} text — 原始文本
 * @returns {string} 转义后的 HTML 安全字符串
 */
function escapeHtml(text) {
    if (!text) return '';
    var div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

/**
 * 时间格式化 — ISO 字符串转为 YYYY-MM-DD HH:mm
 * @param {string} isoStr — ISO 8601 时间字符串
 * @returns {string} 格式化后的时间，无效时返回 '—'
 */
function formatTime(isoStr) {
    if (!isoStr) return '—';
    var d = new Date(isoStr);
    if (isNaN(d.getTime())) return isoStr;
    return d.getFullYear() + '-' +
        String(d.getMonth() + 1).padStart(2, '0') + '-' +
        String(d.getDate()).padStart(2, '0') + ' ' +
        String(d.getHours()).padStart(2, '0') + ':' +
        String(d.getMinutes()).padStart(2, '0');
}

/**
 * Toast 通知 — 创建临时提示，3 秒后自动淡出移除
 * @param {string} message — 提示文本
 * @param {string} [type='info'] — 类型：success / error / info / warning
 */
function showToast(message, type) {
    type = type || 'info';
    var colors = { success: '#16a34a', error: '#dc2626', info: 'rgba(0,0,0,0.85)', warning: '#d97706' };
    var bg = colors[type] || colors.info;

    var container = document.querySelector('.toast-container');
    if (!container) {
        container = document.createElement('div');
        container.className = 'toast-container';
        container.style.position = 'fixed';
        container.style.top = '20px';
        container.style.right = '20px';
        container.style.zIndex = '9999';
        container.style.display = 'flex';
        container.style.flexDirection = 'column';
        container.style.gap = '8px';
        container.style.pointerEvents = 'none';
        document.body.appendChild(container);
    }
    var toast = document.createElement('div');
    toast.className = 'toast toast-' + type;
    toast.textContent = message;
    toast.style.background = bg;
    toast.style.color = '#fff';
    toast.style.padding = '10px 24px';
    toast.style.borderRadius = '6px';
    toast.style.fontSize = '14px';
    toast.style.pointerEvents = 'auto';
    container.appendChild(toast);
    setTimeout(function () {
        toast.style.opacity = '0';
        toast.style.transition = 'opacity 0.3s';
        setTimeout(function () { toast.remove(); }, 300);
    }, 3000);
}

/**
 * 统一 API 请求封装 — 自动注入 CSRF Token
 * @param {string} method — HTTP 方法 (GET/POST/PUT/DELETE)
 * @param {string} url — 请求 URL
 * @param {object} [data] — 请求体数据，GET 请求忽略
 * @returns {Promise} fetch 的 response JSON
 */
function api(method, url, data) {
    var opts = {
        method: method,
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': getCSRFToken()
        }
    };
    if (data) opts.body = JSON.stringify(data);
    return fetch(url, opts).then(function (r) { return r.json(); });
}

/**
 * 批量设置元素 style 属性（满足 CSP style-src 限制，避免 cssText 被拦截）
 * @param {HTMLElement} el — 目标元素
 * @param {object} styles — 键值对 { property: value }
 */
function setStyles(el, styles) {
    Object.keys(styles).forEach(function(k) { el.style[k] = styles[k]; });
}

/**
 * 确认弹窗 — 替代原生 confirm()，统一全站风格
 * @param {string} title — 弹窗标题
 * @param {string} message — 提示消息（支持 \n 换行）
 * @returns {Promise<boolean>} 用户确认返回 true，取消返回 false
 */
function showConfirm(title, message) {
    return new Promise(function(resolve) {
        var safeTitle = escapeHtml(title);
        var safeMsg = escapeHtml(message).replace(/\n/g, '<br>');

        // 遮罩层
        var overlay = document.createElement('div');
        setStyles(overlay, {
            position: 'fixed', inset: '0', background: 'rgba(0,0,0,0.4)',
            zIndex: '9998', display: 'flex', alignItems: 'center', justifyContent: 'center'
        });

        // 弹窗容器
        var box = document.createElement('div');
        setStyles(box, {
            background: '#fff', borderRadius: '8px', padding: '28px 32px',
            minWidth: '320px', maxWidth: '440px',
            boxShadow: '0 8px 30px rgba(0,0,0,0.15)'
        });

        // 标题
        var h3 = document.createElement('h3');
        setStyles(h3, { margin: '0 0 12px 0', fontSize: '17px', color: '#2d3436' });
        h3.textContent = safeTitle;
        box.appendChild(h3);

        // 消息
        var p = document.createElement('p');
        setStyles(p, { margin: '0 0 20px 0', fontSize: '14px', lineHeight: '1.6', color: '#636e72' });
        p.innerHTML = safeMsg; // 已转义，安全
        box.appendChild(p);

        // 按钮容器
        var btnRow = document.createElement('div');
        setStyles(btnRow, { display: 'flex', gap: '10px', justifyContent: 'flex-end' });

        // 取消按钮
        var btnCancel = document.createElement('button');
        setStyles(btnCancel, {
            padding: '8px 20px', border: '1px solid #d1d5db', borderRadius: '6px',
            background: '#fff', color: '#374151', fontSize: '14px', cursor: 'pointer'
        });
        btnCancel.textContent = '取消';
        btnCancel.addEventListener('click', function() { close(false); });
        btnRow.appendChild(btnCancel);

        // 确认按钮
        var btnConfirm = document.createElement('button');
        setStyles(btnConfirm, {
            padding: '8px 20px', border: 'none', borderRadius: '6px',
            background: '#dc2626', color: '#fff', fontSize: '14px', cursor: 'pointer'
        });
        btnConfirm.textContent = '确认';
        btnConfirm.addEventListener('click', function() { close(true); });
        btnRow.appendChild(btnConfirm);

        box.appendChild(btnRow);
        overlay.appendChild(box);
        document.body.appendChild(overlay);

        function close(val) {
            overlay.remove();
            resolve(val);
        }

        overlay.addEventListener('click', function(e) {
            if (e.target === overlay) close(false);
        });
        // Enter 键确认
        var onKey = function(e) {
            if (e.key === 'Enter') { document.removeEventListener('keydown', onKey); close(true); }
            if (e.key === 'Escape') { document.removeEventListener('keydown', onKey); close(false); }
        };
        document.addEventListener('keydown', onKey);
    });
}

/**
 * 输入弹窗 — 替代原生 prompt()，统一全站风格
 * @param {string} message — 提示文本
 * @param {string} [defaultValue=''] — 输入框默认值
 * @returns {Promise<string|null>} 用户输入的值，取消返回 null
 */
function showPrompt(message, defaultValue) {
    return new Promise(function(resolve) {
        var safeMsg = escapeHtml(message);

        // 遮罩层
        var overlay = document.createElement('div');
        setStyles(overlay, {
            position: 'fixed', inset: '0', background: 'rgba(0,0,0,0.4)',
            zIndex: '9998', display: 'flex', alignItems: 'center', justifyContent: 'center'
        });

        // 弹窗容器
        var box = document.createElement('div');
        setStyles(box, {
            background: '#fff', borderRadius: '8px', padding: '28px 32px',
            minWidth: '320px', maxWidth: '440px',
            boxShadow: '0 8px 30px rgba(0,0,0,0.15)'
        });

        // 消息
        var p = document.createElement('p');
        setStyles(p, { margin: '0 0 16px 0', fontSize: '14px', lineHeight: '1.6', color: '#2d3436' });
        p.innerHTML = safeMsg;
        box.appendChild(p);

        // 输入框
        var input = document.createElement('input');
        input.type = 'text';
        input.id = 'mlbPromptInput';
        setStyles(input, {
            width: '100%', padding: '10px 12px', border: '1px solid #d1d5db',
            borderRadius: '6px', fontSize: '14px', color: '#2d3436',
            outline: 'none', boxSizing: 'border-box'
        });
        input.value = escapeHtml(defaultValue || '');
        box.appendChild(input);

        // 按钮容器
        var btnRow = document.createElement('div');
        setStyles(btnRow, { display: 'flex', gap: '10px', justifyContent: 'flex-end', marginTop: '16px' });

        // 取消按钮
        var btnCancel = document.createElement('button');
        setStyles(btnCancel, {
            padding: '8px 20px', border: '1px solid #d1d5db', borderRadius: '6px',
            background: '#fff', color: '#374151', fontSize: '14px', cursor: 'pointer'
        });
        btnCancel.textContent = '取消';
        btnCancel.addEventListener('click', function() { close(null); });
        btnRow.appendChild(btnCancel);

        // 确认按钮
        var btnConfirm = document.createElement('button');
        setStyles(btnConfirm, {
            padding: '8px 20px', border: 'none', borderRadius: '6px',
            background: '#0984e3', color: '#fff', fontSize: '14px', cursor: 'pointer'
        });
        btnConfirm.textContent = '确认';
        btnConfirm.addEventListener('click', function() { close(input.value); });
        btnRow.appendChild(btnConfirm);

        box.appendChild(btnRow);
        overlay.appendChild(box);
        document.body.appendChild(overlay);

        function close(val) {
            overlay.remove();
            resolve(val);
        }

        overlay.addEventListener('click', function(e) {
            if (e.target === overlay) close(null);
        });
        // Enter 确认，Escape 取消
        var onKey = function(e) {
            if (e.key === 'Enter') { document.removeEventListener('keydown', onKey); close(input.value); }
            if (e.key === 'Escape') { document.removeEventListener('keydown', onKey); close(null); }
        };
        document.addEventListener('keydown', onKey);
        // 自动聚焦输入框
        setTimeout(function() { input.focus(); input.select(); }, 50);
    });
}

// 全局头像图片加载失败回退（替代 onerror 内联事件，满足 CSP 无 unsafe-inline）
document.addEventListener('error', function(e) {
    var img = e.target;
    if (img && img.tagName === 'IMG' && (img.classList.contains('nav-avatar') || img.classList.contains('user-avatar-img'))) {
        img.style.display = 'none';
        var next = img.nextElementSibling;
        if (next) next.style.display = 'flex';
    }
}, true);
