import type { StepId } from "../contracts/conversation.js";
import type { AgentEvent } from "../contracts/events.js";
import type { Usage } from "../contracts/provider.js";

export function textDeltaEvent(conversationId: string, turnId: string, delta: string): AgentEvent {
  return { type: "text-delta", conversationId, turnId, delta };
}

export function reasoningDeltaEvent(
  conversationId: string,
  turnId: string,
  delta: string,
): AgentEvent {
  return { type: "reasoning-delta", conversationId, turnId, delta };
}

export function toolCallEvent(
  conversationId: string,
  turnId: string,
  stepId: StepId,
  toolCallId: string,
  toolName: string,
  input: unknown,
): AgentEvent {
  return { type: "tool-call", conversationId, turnId, stepId, toolCallId, toolName, input };
}

export function toolResultEvent(
  conversationId: string,
  turnId: string,
  stepId: StepId,
  toolCallId: string,
  toolName: string,
  content: string,
  isError: boolean,
  durationMs?: number,
): AgentEvent {
  const base = {
    type: "tool-result" as const,
    conversationId,
    turnId,
    stepId,
    toolCallId,
    toolName,
    content,
    isError,
  };
  if (durationMs !== undefined) {
    return { ...base, durationMs };
  }
  return base;
}

export function toolOutputEvent(
  conversationId: string,
  turnId: string,
  toolCallId: string,
  data: string,
  stream: "stdout" | "stderr",
): AgentEvent {
  return { type: "tool-output", conversationId, turnId, toolCallId, data, stream };
}

export function usageEvent(
  conversationId: string,
  turnId: string,
  usage: Usage,
  stepId?: StepId,
): AgentEvent {
  if (stepId !== undefined) {
    return { type: "usage", conversationId, turnId, usage, stepId };
  }
  return { type: "usage", conversationId, turnId, usage };
}

export function turnStartEvent(conversationId: string, turnId: string): AgentEvent {
  return { type: "turn-start", conversationId, turnId };
}

export function stepCompleteEvent(
  conversationId: string,
  turnId: string,
  stepId: StepId,
  timing?: { ttftMs?: number; decodeMs?: number; genTotalMs?: number },
): AgentEvent {
  if (timing !== undefined) {
    if (timing.ttftMs !== undefined) {
      if (timing.decodeMs !== undefined && timing.genTotalMs !== undefined) {
        return {
          type: "step-complete",
          conversationId,
          turnId,
          stepId,
          ttftMs: timing.ttftMs,
          decodeMs: timing.decodeMs,
          genTotalMs: timing.genTotalMs,
        };
      }
      if (timing.genTotalMs !== undefined) {
        return {
          type: "step-complete",
          conversationId,
          turnId,
          stepId,
          ttftMs: timing.ttftMs,
          genTotalMs: timing.genTotalMs,
        };
      }
      return { type: "step-complete", conversationId, turnId, stepId, ttftMs: timing.ttftMs };
    }
    if (timing.genTotalMs !== undefined) {
      return {
        type: "step-complete",
        conversationId,
        turnId,
        stepId,
        genTotalMs: timing.genTotalMs,
      };
    }
  }
  return { type: "step-complete", conversationId, turnId, stepId };
}

export function doneEvent(
  conversationId: string,
  turnId: string,
  reason: string,
  durationMs?: number,
  usage?: Usage,
  contextSize?: number,
): AgentEvent {
  if (durationMs !== undefined && usage !== undefined && contextSize !== undefined) {
    return { type: "done", conversationId, turnId, reason, durationMs, usage, contextSize };
  }
  if (durationMs !== undefined && usage !== undefined) {
    return { type: "done", conversationId, turnId, reason, durationMs, usage };
  }
  if (durationMs !== undefined && contextSize !== undefined) {
    return { type: "done", conversationId, turnId, reason, durationMs, contextSize };
  }
  if (usage !== undefined && contextSize !== undefined) {
    return { type: "done", conversationId, turnId, reason, usage, contextSize };
  }
  if (durationMs !== undefined) {
    return { type: "done", conversationId, turnId, reason, durationMs };
  }
  if (usage !== undefined) {
    return { type: "done", conversationId, turnId, reason, usage };
  }
  if (contextSize !== undefined) {
    return { type: "done", conversationId, turnId, reason, contextSize };
  }
  return { type: "done", conversationId, turnId, reason };
}

export function errorEvent(
  conversationId: string,
  turnId: string,
  message: string,
  code?: string,
): AgentEvent {
  if (code !== undefined) {
    return { type: "error", conversationId, turnId, message, code };
  }
  return { type: "error", conversationId, turnId, message };
}

export function providerRetryEvent(
  conversationId: string,
  turnId: string,
  attempt: number,
  delayMs: number,
  message: string,
  code?: string,
): AgentEvent {
  if (code !== undefined) {
    return { type: "provider-retry", conversationId, turnId, attempt, delayMs, message, code };
  }
  return { type: "provider-retry", conversationId, turnId, attempt, delayMs, message };
}
