'use strict';

const READ_ONLY_TOOL_NAMES = new Set([
  'read_file',
  'glob',
  'grep_files',
  'list_directory',
  'lsp_symbols',
  'lsp_definition',
  'lsp_references',
  'lsp_diagnostics',
  'lsp_hover',
  'lsp_implementation',
]);

const COORDINATION_TOOL_NAMES = new Set([
  'task',
  'update_todos',
  'ask_user',
  'run_shell',
  'check_url',
  'start_static_server',
  'stop_static_server',
  'mcp_call',
  'skill',
]);

const WRITE_TOOL_NAMES = new Set([
  'write_file',
  'edit_file',
  'apply_patch',
  'multi_edit',
]);

const MODES = {
  agent: {
    id: 'agent',
    canEdit: true,
    canDelegate: false,
    description: 'Act as one coding agent. Edit and verify directly; do not delegate through task unless explicitly reconfigured.',
  },
  master: {
    id: 'master',
    canEdit: false,
    canDelegate: true,
    description: 'Act as a master of coding agents. Inspect, plan, verify, and delegate implementation to child agents.',
  },
  mixed: {
    id: 'mixed',
    canEdit: true,
    canDelegate: true,
    description: 'Act as both coding agent and master. Edit directly for tight work and delegate separable work to child agents.',
  },
};

function resolveRuntimeMode(opts = {}, env = process.env) {
  const raw = String(
    opts.runtimeMode
      || opts.codingRole
      || opts.agentRole
      || opts.role
      || (['agent', 'master', 'mixed'].includes(opts.mode) ? opts.mode : '')
      || env.WALLE_CODING_RUNTIME_MODE
      || ''
  ).trim().toLowerCase();
  const id = normalizeRuntimeMode(raw || 'mixed');
  return { ...MODES[id] };
}

function normalizeRuntimeMode(value) {
  const v = String(value || '').trim().toLowerCase();
  if (v === 'delegate' || v === 'delegator' || v === 'orchestrator' || v === 'supervisor') return 'master';
  if (v === 'builder' || v === 'coder' || v === 'single') return 'agent';
  if (v === 'hybrid') return 'mixed';
  if (MODES[v]) return v;
  return 'mixed';
}

function filterToolsForRuntimeMode(tools = [], runtimeMode = resolveRuntimeMode()) {
  const mode = typeof runtimeMode === 'string' ? resolveRuntimeMode({ runtimeMode }) : runtimeMode;
  const list = Array.isArray(tools) ? tools : [];
  if (mode.id === 'mixed') return [...list];
  if (mode.id === 'agent') return list.filter((tool) => tool?.name !== 'task');
  if (mode.id === 'master') {
    return list.filter((tool) => {
      const name = tool?.name || '';
      if (WRITE_TOOL_NAMES.has(name)) return false;
      return READ_ONLY_TOOL_NAMES.has(name) || COORDINATION_TOOL_NAMES.has(name);
    });
  }
  return [...list];
}

function runtimeModeInstructions(runtimeMode = resolveRuntimeMode()) {
  const mode = typeof runtimeMode === 'string' ? resolveRuntimeMode({ runtimeMode }) : runtimeMode;
  if (mode.id === 'master') {
    return [
      'Runtime role: master of coding agents.',
      '- Use task for implementation/review/exploration work that can be delegated.',
      '- You may inspect files and run verification commands, but direct file-editing tools are intentionally unavailable.',
      '- Split work into the fewest independent child tasks; integrate their results and decide final status.',
    ].join('\n');
  }
  if (mode.id === 'agent') {
    return [
      'Runtime role: coding agent.',
      '- Do the coding work directly in this session.',
      '- Delegation is unavailable in this role; use local tools to inspect, edit, and verify.',
    ].join('\n');
  }
  return [
    'Runtime role: mixed coding agent and coordinator.',
    '- Do compact/local edits directly.',
    '- Use task to delegate independent, parallelizable, review, or exploration work.',
    '- Keep the parent session responsible for integration, verification, and final status.',
  ].join('\n');
}

function shouldUseStreamProcessor(opts = {}, env = process.env) {
  if (opts.useStreamProcessor === false) return false;
  if (String(env.WALLE_CODING_STREAM_PROCESSOR || '').trim() === '0') return false;
  return true;
}

module.exports = {
  READ_ONLY_TOOL_NAMES,
  COORDINATION_TOOL_NAMES,
  WRITE_TOOL_NAMES,
  MODES,
  normalizeRuntimeMode,
  resolveRuntimeMode,
  filterToolsForRuntimeMode,
  runtimeModeInstructions,
  shouldUseStreamProcessor,
};
