/**
 * Translate OpenClaw native transcript messages to Friday app ChatMessage format.
 */
import crypto from "node:crypto";
/**
 * Generate a serverId scoped to an OpenClaw transcript entry.
 * Format: msg_<sessionId_short>_<seq>
 * Seq is monotonically increasing per session, good for cursor-based sync.
 */
export function serverIdFromSeq(sessionId, seq) {
    const sid = sessionId.slice(0, 8);
    return `msg_${sid}_${String(seq).padStart(6, "0")}`;
}
/** Generate a standalone serverId (for messages not yet in transcript). */
export function generateStandaloneServerId() {
    const ts = Date.now().toString(36);
    const rand = crypto.randomBytes(6).toString("hex");
    return `msg_${ts}_${rand}`;
}
function extractText(content) {
    if (!content)
        return "";
    if (typeof content === "string")
        return content;
    const parts = [];
    for (const block of content) {
        if (!block || typeof block !== "object")
            continue;
        const t = block.type;
        if (t === "text" || t === "output_text" || t === "input_text") {
            if (typeof block.text === "string")
                parts.push(block.text);
        }
    }
    return parts.join("\n");
}
function extractThinking(content) {
    if (!content || typeof content === "string")
        return "";
    if (!Array.isArray(content))
        return "";
    for (const block of content) {
        if (!block || typeof block !== "object")
            continue;
        if (block.type === "thinking" && typeof block.thinking === "string") {
            return block.thinking;
        }
    }
    return "";
}
function extractToolCalls(content) {
    if (!content || typeof content === "string")
        return null;
    if (!Array.isArray(content))
        return null;
    const calls = [];
    for (const block of content) {
        if (!block || typeof block !== "object")
            continue;
        const t = block.type;
        if (t === "tool_use" || t === "toolcall" || t === "tooluse") {
            calls.push({
                id: block.id ?? "",
                name: block.name ?? "unknown",
                phase: "completed",
                result: null,
                error: null,
                toolCallId: block.id ?? "",
                durationMs: null,
                startTs: null,
                displayLabel: extractDisplayLabel(block.input),
                displayEmoji: null,
            });
        }
    }
    return calls.length > 0 ? calls : null;
}
function extractDisplayLabel(input) {
    if (!input || typeof input !== "object")
        return undefined;
    const obj = input;
    const str = obj.query ?? obj.path ?? obj.url ?? obj.message ?? obj.name ?? obj.text;
    if (typeof str !== "string" || !str.trim())
        return undefined;
    if (str.length <= 80)
        return str;
    return str.slice(0, 77) + "...";
}
function extractThoughtEvents(content) {
    if (!content || typeof content === "string")
        return null;
    if (!Array.isArray(content))
        return null;
    const events = [];
    for (const block of content) {
        if (!block || typeof block !== "object")
            continue;
        const t = block.type;
        if (t === "thinking" && typeof block.thinking === "string") {
            events.push({ kind: "thinking", thinkingText: block.thinking });
        }
        else if (t === "tool_use" || t === "toolcall" || t === "tooluse") {
            events.push({
                kind: "toolCall",
                toolName: block.name ?? "unknown",
                toolCallId: block.id ?? "",
                phase: "completed",
                startTs: null,
                displayLabel: extractDisplayLabel(block.input),
                displayEmoji: null,
            });
        }
        else if (t === "tool_result" || t === "toolresult") {
            events.push({
                kind: "toolResult",
                toolCallId: block.tool_use_id ?? "",
                phase: block.is_error ? "failed" : "completed",
                result: block.content ?? null,
                error: block.is_error ? String(block.content ?? "") : null,
                durationMs: null,
            });
        }
    }
    return events.length > 0 ? events : null;
}
/** Translate a single OpenClaw transcript message to app ChatMessage format. */
export function translateOpenClawMessage(msg, sessionId) {
    const role = (msg.role ?? "").toLowerCase();
    if (role !== "user" && role !== "assistant")
        return null;
    const isFromCurrentUser = role === "user";
    const content = extractText(msg.content);
    const thinking = extractThinking(msg.content);
    const toolCalls = extractToolCalls(msg.content);
    const thoughtEvents = extractThoughtEvents(msg.content);
    const entryId = msg.__openclaw?.id ?? "";
    const seq = msg.__openclaw?.seq ?? 0;
    const totalTokens = msg.usage?.totalTokens ?? msg.usage?.total_tokens ?? null;
    const ts = msg.timestamp ? new Date(msg.timestamp).toISOString() : new Date().toISOString();
    const sender = isFromCurrentUser
        ? { user: { name: "You" } }
        : { assistant: { name: "Claude" } };
    return {
        id: "",
        content,
        sender,
        timestamp: ts,
        seq,
        status: "sent",
        isFromCurrentUser,
        toolCalls,
        attachment: null,
        extraAttachments: null,
        thoughtEvents,
        ttsAttachment: null,
        commandTerminals: null,
        isInternalTrace: false,
        modelName: msg.model ?? null,
        totalTokens,
        contextWindowMax: null,
        contextTokensUsed: null,
        runId: null,
        serverId: seq > 0 ? serverIdFromSeq(sessionId, seq) : null,
    };
}
/** Translate an array of OpenClaw messages, filtering out non-user/assistant roles. */
export function translateOpenClawMessages(messages, sessionId) {
    return messages
        .map((m) => translateOpenClawMessage(m, sessionId))
        .filter((m) => m !== null);
}
