'use strict';

const crypto = require('node:crypto');
const { normalizeAgentMode, normalizeAgentRunResult } = require('./contract');
const {
  runCommand,
  getChangedFiles,
  getDiff,
  parseJsonObject,
} = require('./utils');

function buildGeminiArgs(prompt, opts = {}) {
  const args = [];
  if (opts.model) args.push('--model', opts.model);
  args.push('--prompt', prompt);
  args.push('--output-format', opts.outputFormat || 'json');
  if (opts.approvalMode) args.push('--approval-mode', opts.approvalMode);
  if (opts.sandbox === true) args.push('--sandbox');
  if (opts.includeDirectories) {
    const dirs = Array.isArray(opts.includeDirectories)
      ? opts.includeDirectories.join(',')
      : String(opts.includeDirectories);
    args.push('--include-directories', dirs);
  }
  return args;
}

function normalizeGeminiJson(parsed) {
  if (!parsed || typeof parsed !== 'object') return { output: '', usage: null, events: [] };
  const output = typeof parsed.response === 'string' ? parsed.response : '';
  const stats = parsed.stats || null;
  const events = stats ? [{ type: 'gemini.stats', stats }] : [];
  return { output, usage: stats ? { stats } : null, events };
}

async function runTask(options = {}) {
  const prompt = options.prompt || '';
  const cwd = options.cwd || process.cwd();
  const mode = normalizeAgentMode(options.mode);
  const sessionId = options.sessionId || crypto.randomUUID();
  const args = buildGeminiArgs(prompt, options);
  const result = await runCommand('gemini', args, {
    cwd,
    env: process.env,
    timeoutMs: options.timeoutMs || 300000,
    maxOutputBytes: options.maxOutputBytes,
  });

  const parsed = parseJsonObject(result.output);
  const normalized = normalizeGeminiJson(parsed);
  const changedFiles = getChangedFiles(cwd);
  const errorText = parsed?.error?.message
    ? `${result.stderr}${result.stderr ? '\n' : ''}${parsed.error.message}`
    : result.stderr;

  return normalizeAgentRunResult({
    runnerId: 'gemini',
    providerType: 'google',
    mode,
    success: result.success && !parsed?.error,
    output: normalized.output || result.output,
    stderr: result.timedOut
      ? `${errorText}${errorText ? '\n' : ''}Timed out after ${options.timeoutMs || 300000}ms`
      : errorText,
    sessionId,
    resumeHandle: sessionId,
    exitCode: result.exitCode,
    timedOut: result.timedOut,
    signal: result.signal,
    latencyMs: result.latencyMs,
    events: normalized.events,
    changedFiles,
    diff: getDiff(cwd, changedFiles),
    usage: normalized.usage,
    artifacts: {
      command: 'gemini',
      outputFormat: options.outputFormat || 'json',
    },
  });
}

module.exports = {
  id: 'gemini',
  providerType: 'google',
  kind: 'cli-agent',
  capabilities: {
    modes: ['plan', 'build', 'review', 'analysis'],
    jsonOutput: true,
    streamJson: true,
    resume: true,
    worktree: true,
  },
  buildGeminiArgs,
  normalizeGeminiJson,
  runTask,
};
