/**
 * CursorHostEventMapper — Cursor SDK message / RuntimeEvent → HostEvent (WP-04).
 * Cursor-specific; generic contracts remain vendor-agnostic.
 */

import { randomUUID } from "node:crypto";

import type { RuntimeEvent, RuntimeEventType } from "../../../types/state.ts";
import type { HostEventEnvelope } from "../../contracts/HostEvent.ts";
import { toHostEventEnvelope } from "../../contracts/HostEvent.ts";

/**
 * Map a Cursor SDK `SDKMessage.type` to RuntimeEventType.
 * Behavioral baseline matches SdkRunHandle decision M (spike ringer.ts).
 */
export function mapCursorSdkMessageType(t: string): RuntimeEventType {
  switch (t) {
    case "system":
      return "sdk.system";
    case "thinking":
      return "sdk.thinking";
    case "assistant":
      return "sdk.assistant";
    case "tool_call":
      return "sdk.tool_call";
    case "status":
      return "sdk.status";
    case "task":
      return "sdk.task";
    case "request":
      return "sdk.request";
    case "user":
      return "sdk.user";
    case "result":
      return "sdk.result";
    default:
      return "sdk.system";
  }
}

/** Map RuntimeEventType to Host event type string (stable prefix set). */
export function mapCursorRuntimeEventTypeToHostType(
  eventType: RuntimeEventType | string,
): string {
  switch (eventType) {
    case "sdk.thinking":
      return "host.thinking";
    case "sdk.assistant":
      return "host.assistant";
    case "sdk.tool_call":
      return "host.tool_call";
    case "sdk.tool_result":
      return "host.tool_result";
    case "sdk.status":
      return "host.status";
    case "sdk.result":
      return "host.run.completed";
    case "runtime.session_started":
      return "host.session.started";
    case "runtime.session_ended":
      return "host.session.ended";
    case "runtime.session_cancelled":
      return "host.run.cancelled";
    default:
      return typeof eventType === "string" && eventType.trim()
        ? eventType
        : "host.event.opaque";
  }
}

export type CursorHostEventMapInput = {
  hostId: string;
  workerId: string;
  runId: string;
  event: RuntimeEvent;
};

/**
 * Convert a Cursor-backed RuntimeEvent into a HostEventEnvelope.
 * Unknown/opaque types keep original material in `raw`.
 */
export function mapCursorRuntimeEventToHostEnvelope(
  input: CursorHostEventMapInput,
): HostEventEnvelope {
  const { event } = input;
  const type = mapCursorRuntimeEventTypeToHostType(event.event_type);
  return toHostEventEnvelope({
    eventId: event.event_id || `evt-${randomUUID()}`,
    at: event.at || new Date().toISOString(),
    hostId: input.hostId,
    workerId: input.workerId,
    runId: input.runId,
    type,
    payload: event.payload,
    raw: event,
  });
}
