import sessionManager from '../../../../sessionManager.js';
import { getQwenCliSessionMessages } from '../../../../projects.js';
import { createNormalizedMessage, generateMessageId, readObjectRecord } from '../../../../shared/utils.js';
const PROVIDER = 'qwen';
/**
 * Qwen Code sessions — structurally identical to Gemini since Qwen is a fork.
 * Stream events have the same `type` taxonomy (message / tool_use /
 * tool_result / result / error), and on-disk history files carry the same
 * `role + content` message shape with optional part arrays.
 */
export class QwenSessionsProvider {
    normalizeMessage(rawMessage, sessionId) {
        const raw = readObjectRecord(rawMessage);
        if (!raw)
            return [];
        const ts = raw.timestamp || new Date().toISOString();
        const baseId = raw.uuid || generateMessageId('qwen');
        // Qwen Code stream-json (verified from `qwen --output-format stream-json --yolo`):
        //   { type:"system", subtype:"init", session_id, ... }
        //   { type:"assistant", uuid, session_id, message:{ role:"assistant", content:[{type:"text", text:"…"}], usage:{...} } }
        //   { type:"result",  subtype:"success", result:"…final…", usage:{...} }
        // The previous matcher (`type==='message' && role==='assistant'`) checked
        // a shape Qwen has never emitted — every chat returned empty messages,
        // including API-error messages like "[API Error: 401 invalid access token
        // or token expired]" which then landed in the void instead of reaching
        // the user. Match the real shape.
        if (raw.type === 'assistant' && raw.message && typeof raw.message === 'object') {
            const msg = raw.message;
            const parts = Array.isArray(msg.content) ? msg.content : [];
            const text = parts
                .map((p) => (typeof p?.text === 'string' ? p.text : ''))
                .filter(Boolean)
                .join('');
            const messages = [];
            if (text) {
                messages.push(createNormalizedMessage({
                    id: baseId,
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'stream_delta',
                    content: text,
                }));
            }
            // Surface tool_use parts inline so the agent route can see them too.
            for (const part of parts) {
                if (part?.type === 'tool_use') {
                    messages.push(createNormalizedMessage({
                        id: typeof part.id === 'string' ? part.id : generateMessageId('qwen'),
                        sessionId,
                        timestamp: ts,
                        provider: PROVIDER,
                        kind: 'tool_use',
                        toolName: typeof part.name === 'string' ? part.name : '',
                        toolInput: part.input || {},
                        toolId: typeof part.id === 'string' ? part.id : '',
                    }));
                }
            }
            return messages;
        }
        // Legacy `type:"message"` shape — kept so any persisted history that
        // pre-dates the stream-json migration still parses cleanly.
        if (raw.type === 'message' && raw.role === 'assistant') {
            const content = raw.content || '';
            const messages = [];
            if (content) {
                messages.push(createNormalizedMessage({
                    id: baseId,
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'stream_delta',
                    content,
                }));
            }
            if (raw.delta !== true) {
                messages.push(createNormalizedMessage({
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'stream_end',
                }));
            }
            return messages;
        }
        if (raw.type === 'tool_use') {
            return [createNormalizedMessage({
                    id: baseId,
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'tool_use',
                    toolName: raw.tool_name,
                    toolInput: raw.parameters || {},
                    toolId: raw.tool_id || baseId,
                })];
        }
        if (raw.type === 'tool_result') {
            return [createNormalizedMessage({
                    id: baseId,
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'tool_result',
                    toolId: raw.tool_id || '',
                    content: raw.output === undefined ? '' : String(raw.output),
                    isError: raw.status === 'error',
                })];
        }
        if (raw.type === 'result') {
            const messages = [createNormalizedMessage({
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'stream_end',
                })];
            if (raw.stats?.total_tokens) {
                messages.push(createNormalizedMessage({
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'status',
                    text: 'Complete',
                    tokens: raw.stats.total_tokens,
                    canInterrupt: false,
                }));
            }
            return messages;
        }
        if (raw.type === 'error') {
            return [createNormalizedMessage({
                    id: baseId,
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'error',
                    content: raw.error || raw.message || 'Unknown Qwen Code streaming error',
                })];
        }
        return [];
    }
    async fetchHistory(sessionId, options = {}) {
        const { limit = null, offset = 0 } = options;
        let rawMessages;
        try {
            rawMessages = sessionManager.getSessionMessages(sessionId);
            if (rawMessages.length === 0) {
                rawMessages = await getQwenCliSessionMessages(sessionId);
            }
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            console.warn(`[QwenProvider] Failed to load session ${sessionId}:`, message);
            return { messages: [], total: 0, hasMore: false, offset: 0, limit: null };
        }
        const normalized = [];
        for (let i = 0; i < rawMessages.length; i++) {
            const raw = rawMessages[i];
            const ts = raw.timestamp || new Date().toISOString();
            const baseId = raw.uuid || generateMessageId('qwen');
            const role = raw.message?.role || raw.role;
            const content = raw.message?.content || raw.content;
            if (!role || !content)
                continue;
            const normalizedRole = role === 'user' ? 'user' : 'assistant';
            if (Array.isArray(content)) {
                for (let partIdx = 0; partIdx < content.length; partIdx++) {
                    const part = content[partIdx];
                    if (part.type === 'text' && part.text) {
                        normalized.push(createNormalizedMessage({
                            id: `${baseId}_${partIdx}`,
                            sessionId,
                            timestamp: ts,
                            provider: PROVIDER,
                            kind: 'text',
                            role: normalizedRole,
                            content: part.text,
                        }));
                    }
                    else if (part.type === 'tool_use') {
                        normalized.push(createNormalizedMessage({
                            id: `${baseId}_${partIdx}`,
                            sessionId,
                            timestamp: ts,
                            provider: PROVIDER,
                            kind: 'tool_use',
                            toolName: part.name,
                            toolInput: part.input,
                            toolId: part.id || generateMessageId('qwen_tool'),
                        }));
                    }
                    else if (part.type === 'tool_result') {
                        normalized.push(createNormalizedMessage({
                            id: `${baseId}_${partIdx}`,
                            sessionId,
                            timestamp: ts,
                            provider: PROVIDER,
                            kind: 'tool_result',
                            toolId: part.tool_use_id || '',
                            content: part.content === undefined ? '' : String(part.content),
                            isError: Boolean(part.is_error),
                        }));
                    }
                }
            }
            else if (typeof content === 'string' && content.trim()) {
                normalized.push(createNormalizedMessage({
                    id: baseId,
                    sessionId,
                    timestamp: ts,
                    provider: PROVIDER,
                    kind: 'text',
                    role: normalizedRole,
                    content,
                }));
            }
        }
        const toolResultMap = new Map();
        for (const msg of normalized) {
            if (msg.kind === 'tool_result' && msg.toolId) {
                toolResultMap.set(msg.toolId, msg);
            }
        }
        for (const msg of normalized) {
            if (msg.kind === 'tool_use' && msg.toolId && toolResultMap.has(msg.toolId)) {
                const toolResult = toolResultMap.get(msg.toolId);
                if (toolResult) {
                    msg.toolResult = { content: toolResult.content, isError: toolResult.isError };
                }
            }
        }
        const start = Math.max(0, offset);
        const pageLimit = limit === null ? null : Math.max(0, limit);
        const messages = pageLimit === null
            ? normalized.slice(start)
            : normalized.slice(start, start + pageLimit);
        return {
            messages,
            total: normalized.length,
            hasMore: pageLimit === null ? false : start + pageLimit < normalized.length,
            offset: start,
            limit: pageLimit,
        };
    }
}
//# sourceMappingURL=qwen-sessions.provider.js.map