// Filename: frontend/js/pages/logs/logList.js
import { escapeHTML } from '../../utils/utils.js';

export const STATIC_ERROR_MAP = {
    'API_KEY_INVALID': { type: '密钥无效', style: 'red' },
    'INVALID_ARGUMENT': { type: '参数无效', style: 'red' },
    'PERMISSION_DENIED': { type: '权限不足', style: 'red' },
    'NOT_FOUND': { type: '资源未找到', style: 'gray' },
    'RESOURCE_EXHAUSTED': { type: '资源耗尽', style: 'orange' },
    'QUOTA_EXCEEDED': { type: '配额耗尽', style: 'orange' },
    'DEADLINE_EXCEEDED': { type: '请求超时', style: 'yellow' },
    'CANCELLED': { type: '请求已取消', style: 'gray' },
    'INTERNAL': { type: 'Google内部错误', style: 'yellow' },
    'UNAVAILABLE': { type: '服务不可用', style: 'yellow' },
};
// --- HTTP状态码到类型和样式的动态映射表 ---
export const STATUS_CODE_MAP = {
    400: { type: '错误请求', style: 'red' },
    401: { type: '认证失败', style: 'red' },
    403: { type: '禁止访问', style: 'red' },
    404: { type: '资源未找到', style: 'gray' },
    413: { type: '请求体过大', style: 'orange' },
    429: { type: '请求频率过高', style: 'orange' },
    500: { type: '内部服务错误', style: 'yellow' },
    503: { type: '服务不可用', style: 'yellow' }
};
const SPECIAL_CASE_MAP = [
    { code: 400, keyword: 'api key not found', type: '无效密钥', style: 'red' },
    { code: 404, keyword: 'call listmodels', type: '模型配置错误', style: 'orange' }
];

// --- 样式名称到 Tailwind 类的转换器 ---
const styleToClass = (style) => {
    switch (style) {
        case 'red': return 'bg-red-500/10 text-red-600';
        case 'orange': return 'bg-orange-500/10 text-orange-600';
        case 'yellow': return 'bg-yellow-500/10 text-yellow-600';
        case 'gray': return 'bg-zinc-500/10 text-zinc-600';
        default: return 'bg-destructive/10 text-destructive';
    }
};


const errorCodeRegex = /(\d+)$/;

class LogList {
    constructor(container, dataStore) {
        this.container = container;
        this.dataStore = dataStore; 
        if (!this.container) console.error("LogList: container element (tbody) not found.");
    }

    renderLoading() {
        if (!this.container) return;
        this.container.innerHTML = `<tr><td colspan="9" class="p-8 text-center text-muted-foreground"><i class="fas fa-spinner fa-spin mr-2"></i> 加载日志中...</td></tr>`;
    }

    render(logs, pagination, selectedLogIds) {
        if (!this.container) return;
        if (!logs || logs.length === 0) {
            this.container.innerHTML = `<tr><td colspan="9" class="p-8 text-center text-muted-foreground">没有找到相关的日志记录。</td></tr>`;
            return;
        }
        const { page, page_size } = pagination;
        const startIndex = (page - 1) * page_size;
        const logsHtml = logs.map((log, index) => {
            const isChecked = selectedLogIds.has(log.ID);
            return this.createLogRowHtml(log, startIndex + index + 1, isChecked);
        }).join('');
        this.container.innerHTML = logsHtml;
    }

    _interpretError(log) {
        // 1. 成功状态
        if (log.IsSuccess) {
            return {
                type: 'N/A',
                statusCodeHtml: `<span class="inline-flex items-center rounded-md bg-green-500/10 px-2 py-1 text-xs font-medium text-green-600">成功</span>`
            };
        }
        // 2. [新增] 特殊场景优先判断 (结合ErrorCode和ErrorMessage)
        const codeMatch = log.ErrorCode ? log.ErrorCode.match(errorCodeRegex) : null;
        if (codeMatch && codeMatch[1] && log.ErrorMessage) {
            const code = parseInt(codeMatch[1], 10);
            const lowerCaseMsg = log.ErrorMessage.toLowerCase();
            for (const rule of SPECIAL_CASE_MAP) {
                if (code === rule.code && lowerCaseMsg.includes(rule.keyword)) {
                    return {
                        type: rule.type,
                        statusCodeHtml: `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${styleToClass(rule.style)}">${code}</span>`
                    };
                }
            }
        }
        // 3. 静态错误码匹配 (例如 "INVALID_ARGUMENT")
        if (log.ErrorCode && STATIC_ERROR_MAP[log.ErrorCode]) {
            const mapping = STATIC_ERROR_MAP[log.ErrorCode];
            return {
                type: mapping.type,
                statusCodeHtml: `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${styleToClass(mapping.style)}">${log.ErrorCode}</span>`
            };
        }
        // 4. 动态解析HTTP状态码 (例如 "UPSTREAM_429")
        if (codeMatch && codeMatch[1]) {
            const code = parseInt(codeMatch[1], 10);
            let mapping = STATUS_CODE_MAP[code];
            // 为所有 5xx 错误提供降级
            if (!mapping && code >= 500 && code < 600) {
                mapping = STATUS_CODE_MAP[500];
            }
            if (mapping) {
                return {
                    type: mapping.type,
                    statusCodeHtml: `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${styleToClass(mapping.style)}">${code}</span>`
                };
            }
        }
        // 5. 边界情况: ErrorCode 和 ErrorMessage 都为空
        if (!log.ErrorCode && !log.ErrorMessage) {
            return { type: '未知', statusCodeHtml: `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${styleToClass('gray')}">N/A</span>` };
        }
        // 6. 最终的降级处理
        return { type: '未知错误', statusCodeHtml: `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${styleToClass('default')}">失败</span>` };
    }
    
    _formatModelName(modelName) {
        const styleClass = ''; 
        return `<div class="inline-block rounded bg-zinc-100 dark:bg-zinc-800 px-2 py-0.5"><span class="font-quinquefive text-xs tracking-wider ${styleClass}">${modelName}</span></div>`;
    }
    
    createLogRowHtml(log, index, isChecked) {
        const group = this.dataStore.groups.get(log.GroupID);
        const groupName = group ? group.display_name : (log.GroupID ? `Group #${log.GroupID}` : 'N/A');
        const key = this.dataStore.keys.get(log.KeyID);
        let apiKeyDisplay;
        if (key && key.APIKey && key.APIKey.length >= 8) {
            const masked = `${key.APIKey.substring(0, 4)}......${key.APIKey.substring(key.APIKey.length - 4)}`;
            apiKeyDisplay = escapeHTML(masked);
        } else {
            apiKeyDisplay = log.KeyID ? `Key #${log.KeyID}` : 'N/A';
        }
        const errorInfo = this._interpretError(log);
        const modelNameFormatted = this._formatModelName(log.ModelName);
        const errorMessageAttr = log.ErrorMessage ? `data-error-message="${escape(log.ErrorMessage)}"` : '';
        const requestTime = new Date(log.RequestTime).toLocaleString();
        
        const checkedAttr = isChecked ? 'checked' : '';
        return `
            <tr class="table-row" data-log-id="${log.ID}" ${errorMessageAttr}>
                <td class="table-cell">
                    <input type="checkbox" class="h-4 w-4 rounded border-zinc-300 text-blue-600 focus:ring-blue-500" ${checkedAttr}>
                </td>
                <td class="table-cell font-mono text-muted-foreground">${index}</td>
                <td class="table-cell font-medium font-mono">${apiKeyDisplay}</td>
                <td class="table-cell">${groupName}</td>
                <td class="table-cell">${errorInfo.type}</td>
                <td class="table-cell">${errorInfo.statusCodeHtml}</td>
                <td class="table-cell">${modelNameFormatted}</td>
                <td class="table-cell text-muted-foreground text-xs">${requestTime}</td>
                <td class="table-cell">
                    <button class="btn btn-ghost btn-icon btn-sm" aria-label="查看详情">
                        <i class="fas fa-ellipsis-h h-4 w-4"></i>
                    </button>
                </td>
            </tr>
        `;
    }
}
export default LogList;
