'use strict';

const crypto = require('node:crypto');

const AGENT_MODES = Object.freeze(['plan', 'build', 'review', 'analysis']);

function createAgentRunId(prefix = 'agent-run') {
  return `${prefix}-${crypto.randomUUID()}`;
}

function normalizeAgentMode(mode) {
  return AGENT_MODES.includes(mode) ? mode : 'build';
}

function normalizeAgentRunResult(result = {}, fallback = {}) {
  const sessionId = result.sessionId || fallback.sessionId || crypto.randomUUID();
  const runId = result.runId || fallback.runId || createAgentRunId();
  const exitCode = Number.isInteger(result.exitCode) ? result.exitCode : (result.success ? 0 : -1);
  const errors = Array.isArray(result.errors)
    ? result.errors
    : (result.error ? [{ message: String(result.error) }] : []);
  return {
    id: runId,
    runId,
    parentRunId: result.parentRunId || fallback.parentRunId || null,
    runnerId: result.runnerId || fallback.runnerId || 'unknown',
    providerType: result.providerType || fallback.providerType || 'unknown',
    kind: 'cli-agent',
    mode: normalizeAgentMode(result.mode || fallback.mode),
    success: Boolean(result.success),
    output: result.output || '',
    outputRaw: result.outputRaw || null,
    stderr: result.stderr || '',
    sessionId,
    resumeHandle: result.resumeHandle || sessionId,
    session: {
      id: sessionId,
      resumeToken: result.resumeHandle || sessionId,
      persistent: Boolean(result.persistent ?? fallback.persistent),
      cleanupPolicy: result.cleanupPolicy || fallback.cleanupPolicy || 'delete-on-complete',
      threadId: result.threadId || fallback.threadId || null,
      status: result.sessionStatus || fallback.sessionStatus || null,
    },
    exitCode,
    timedOut: Boolean(result.timedOut),
    signal: result.signal || null,
    latencyMs: result.latencyMs || null,
    events: Array.isArray(result.events) ? result.events : [],
    changedFiles: Array.isArray(result.changedFiles) ? result.changedFiles : [],
    diff: result.diff || '',
    usage: result.usage || null,
    costEstimate: result.costEstimate || null,
    trace: result.trace || fallback.trace || null,
    artifacts: result.artifacts || {},
    errors,
  };
}

function createUnavailableResult({ runnerId, providerType, mode, sessionId, error }) {
  return normalizeAgentRunResult({
    runnerId,
    providerType,
    mode,
    sessionId,
    success: false,
    output: '',
    stderr: error || 'Agent runner unavailable',
    exitCode: -1,
  });
}

module.exports = {
  AGENT_MODES,
  createAgentRunId,
  normalizeAgentMode,
  normalizeAgentRunResult,
  createUnavailableResult,
};
