export const RUNTIME_TIMELINE_PUBLIC_SOURCE = "runtime";
export const RUNTIME_TIMELINE_EVENT_TYPES = [
    "runtime_event",
    "runtime_message",
    "runtime_permission",
    "runtime_session",
    "runtime_tool",
];
export const RUNTIME_TIMELINE_TONES = [
    "primary",
    "success",
    "warning",
    "destructive",
    "muted",
];
export const RUNTIME_TIMELINE_METADATA_KEYS = [
    "category",
    "status",
    "risk",
];
const MAX_PUBLIC_ID_LENGTH = 96;
const FALLBACK_EVENT_ID = "rte_unavailable";
const FALLBACK_OCCURRED_AT = "1970-01-01T00:00:00.000Z";
const PRESENTATION_BY_TYPE = {
    runtime_event: {
        title: "Runtime event",
        description: "The runtime reported activity.",
        defaultTone: "muted",
    },
    runtime_message: {
        title: "Runtime message activity",
        description: "The runtime reported message activity.",
        defaultTone: "primary",
    },
    runtime_permission: {
        title: "Runtime permission activity",
        description: "The runtime reported permission activity.",
        defaultTone: "warning",
    },
    runtime_session: {
        title: "Runtime session activity",
        description: "The runtime reported session activity.",
        defaultTone: "primary",
    },
    runtime_tool: {
        title: "Runtime tool activity",
        description: "The runtime reported tool activity.",
        defaultTone: "primary",
    },
};
const CATEGORY_BY_TYPE = {
    runtime_event: "event",
    runtime_message: "message",
    runtime_permission: "permission",
    runtime_session: "session",
    runtime_tool: "tool",
};
const STATUSES_BY_CATEGORY = {
    event: [],
    message: ["created", "updated", "completed", "failed"],
    permission: ["requested", "updated", "answered", "failed"],
    session: ["created", "updated", "ended", "failed"],
    tool: ["started", "completed", "failed"],
};
const RISK_VALUES = [
    "low",
    "medium",
    "high",
    "read",
    "write",
    "external_service_mutation",
];
const RAW_OPENCODE_TYPE_RULES = [
    {
        prefixes: ["permission.requested", "session.permission.ask"],
        classification: {
            type: "runtime_permission",
            category: "permission",
            status: "requested",
        },
    },
    {
        prefixes: ["permission.updated"],
        classification: {
            type: "runtime_permission",
            category: "permission",
            status: "updated",
        },
    },
    {
        prefixes: ["message.updated"],
        classification: {
            type: "runtime_message",
            category: "message",
            status: "updated",
        },
    },
    {
        prefixes: ["message.created"],
        classification: {
            type: "runtime_message",
            category: "message",
            status: "created",
        },
    },
    {
        prefixes: ["message.completed"],
        classification: {
            type: "runtime_message",
            category: "message",
            status: "completed",
        },
    },
    {
        prefixes: ["message.failed", "message.error"],
        classification: {
            type: "runtime_message",
            category: "message",
            status: "failed",
        },
    },
    {
        prefixes: ["session.created"],
        classification: {
            type: "runtime_session",
            category: "session",
            status: "created",
        },
    },
    {
        prefixes: ["session.updated"],
        classification: {
            type: "runtime_session",
            category: "session",
            status: "updated",
        },
    },
    {
        prefixes: ["session.deleted", "session.ended"],
        classification: {
            type: "runtime_session",
            category: "session",
            status: "ended",
        },
    },
    {
        prefixes: ["tool.started", "tool.call.started"],
        classification: {
            type: "runtime_tool",
            category: "tool",
            status: "started",
        },
    },
    {
        prefixes: ["tool.completed", "tool.call.completed"],
        classification: {
            type: "runtime_tool",
            category: "tool",
            status: "completed",
        },
    },
    {
        prefixes: ["tool.failed", "tool.error", "tool.call.failed"],
        classification: {
            type: "runtime_tool",
            category: "tool",
            status: "failed",
        },
    },
];
const GENERIC_EVENT_CLASSIFICATION = {
    type: "runtime_event",
    category: "event",
};
export function projectOpenCodeRuntimeTimelineEvent(rawType) {
    return buildProjection(classifyOpenCodeRuntimeEventType(rawType));
}
export function formatRuntimeTimelineRecord(record) {
    const metadata = isRecord(record.metadata) ? record.metadata : {};
    const type = readRuntimeTimelineEventType(record.type) ?? "runtime_event";
    const category = CATEGORY_BY_TYPE[type];
    const status = readStatusForCategory(category, metadata.status);
    const classification = { type, category };
    if (status)
        classification.status = status;
    const projection = buildProjection(classification);
    const risk = readRuntimeTimelineRisk(metadata.risk);
    if (risk)
        projection.metadata.risk = risk;
    return {
        id: formatPublicEventId(record.id),
        source: RUNTIME_TIMELINE_PUBLIC_SOURCE,
        type: projection.type,
        at: formatPublicTimestamp(record.occurredAt, record.createdAt),
        title: projection.title,
        description: projection.description,
        tone: projection.tone,
        metadata: projection.metadata,
    };
}
export function isRuntimeTimelineEventType(value) {
    return (typeof value === "string" &&
        RUNTIME_TIMELINE_EVENT_TYPES.includes(value));
}
export function isRuntimeTimelineTone(value) {
    return (typeof value === "string" &&
        RUNTIME_TIMELINE_TONES.includes(value));
}
export function isRuntimeTimelinePublicSource(value) {
    return value === RUNTIME_TIMELINE_PUBLIC_SOURCE;
}
function classifyOpenCodeRuntimeEventType(rawType) {
    if (typeof rawType !== "string")
        return GENERIC_EVENT_CLASSIFICATION;
    const normalized = rawType.trim().toLowerCase();
    if (!normalized)
        return GENERIC_EVENT_CLASSIFICATION;
    for (const rule of RAW_OPENCODE_TYPE_RULES) {
        if (rule.prefixes.some((prefix) => matchesRawTypePrefix(normalized, prefix))) {
            return rule.classification;
        }
    }
    return GENERIC_EVENT_CLASSIFICATION;
}
function matchesRawTypePrefix(value, prefix) {
    return value === prefix || value.startsWith(`${prefix}:`);
}
function buildProjection(classification) {
    const presentation = PRESENTATION_BY_TYPE[classification.type];
    const metadata = {
        category: classification.category,
    };
    if (classification.status)
        metadata.status = classification.status;
    return {
        type: classification.type,
        title: presentation.title,
        description: presentation.description,
        tone: toneForClassification(classification, presentation),
        metadata,
    };
}
function toneForClassification(classification, presentation) {
    if (classification.status === "failed")
        return "destructive";
    if (classification.status === "completed" &&
        classification.type !== "runtime_tool") {
        return "success";
    }
    return presentation.defaultTone;
}
function readRuntimeTimelineEventType(value) {
    return isRuntimeTimelineEventType(value) ? value : undefined;
}
function readStatusForCategory(category, value) {
    if (typeof value !== "string")
        return undefined;
    const statuses = STATUSES_BY_CATEGORY[category];
    return statuses.includes(value)
        ? value
        : undefined;
}
function readRuntimeTimelineRisk(value) {
    if (typeof value !== "string")
        return undefined;
    return RISK_VALUES.includes(value)
        ? value
        : undefined;
}
function formatPublicEventId(value) {
    if (typeof value !== "string" || value.length === 0)
        return FALLBACK_EVENT_ID;
    if (containsTokenLikeSecret(value))
        return FALLBACK_EVENT_ID;
    const bounded = value
        .replace(/[^A-Za-z0-9_.:-]/gu, "_")
        .slice(0, MAX_PUBLIC_ID_LENGTH);
    return bounded.length > 0 ? bounded : FALLBACK_EVENT_ID;
}
function formatPublicTimestamp(occurredAt, createdAt) {
    return (readIsoTimestamp(occurredAt) ??
        readIsoTimestamp(createdAt) ??
        FALLBACK_OCCURRED_AT);
}
function readIsoTimestamp(value) {
    if (typeof value !== "string")
        return undefined;
    if (value.length > 64)
        return undefined;
    if (containsTokenLikeSecret(value))
        return undefined;
    const timestamp = Date.parse(value);
    if (!Number.isFinite(timestamp))
        return undefined;
    return new Date(timestamp).toISOString();
}
function containsTokenLikeSecret(value) {
    return (/\bsk-[A-Za-z0-9_-]{6,}\b/u.test(value) ||
        /-----BEGIN [A-Z ]*PRIVATE KEY-----/u.test(value) ||
        /\/Users\/[^\s]+/u.test(value));
}
function isRecord(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
