import type { SubagentToolManifestItem } from '../subagent/process_protocol.js';

export type ToolWorkerRoutingStrategy =
  | 'auto'
  | 'force-local'
  | 'force-main-process-proxy'
  | 'force-disabled';

export type ToolGovernanceExtra = {
  allowInSubagent?: boolean;
  workerRoutingStrategy?: ToolWorkerRoutingStrategy;
  imageDefaults?: {
    n?: number;
    aspectRatio?: string;
    width?: number;
    height?: number;
    watermark?: boolean;
    responseFormat?: 'url' | 'base64';
  };
  imageConstraints?: {
    maxN?: number;
    maxWidth?: number;
    maxHeight?: number;
  };
};

export type ToolManifestConfig = {
  visibility?: SubagentToolManifestItem['visibility'] | string;
  capability?: SubagentToolManifestItem['capability'] | string;
};

export type ToolRuntimeProfile = Pick<
  SubagentToolManifestItem,
  | 'kind'
  | 'executionMode'
  | 'supportedInWorker'
  | 'workerRoutingHint'
  | 'requiresShell'
  | 'requiresWrite'
  | 'requiresSkillScope'
>;

const LOCAL_WORKER_TOOLS = new Set([
  'bash',
  'read_file',
  'list_dir',
  'find_files',
  'grep',
]);

const MAIN_PROCESS_PROXY_TOOLS = new Set([
  'write_file',
  'edit',
  'patch',
  'read_skill',
  'read_skill_file',
  'skill_manage',
  'memory_save',
  'memory_recall',
]);

const SEQUENTIAL_TOOLS = new Set([
  'edit',
  'patch',
  'write_file',
  'delegate_task',
  'delegate_parallel',
  'clarify',
  'escalate',
]);

const WORKSPACE_ROOT_TOOLS = new Set([
  'bash',
  'read_file',
  'list_dir',
  'find_files',
  'grep',
  'write_file',
  'edit',
  'patch',
]);

export function toToolKind(name: string): SubagentToolManifestItem['kind'] {
  if (name.startsWith('memory_')) return 'memory';
  if (name.startsWith('read_skill') || name === 'skill_manage') return 'skill';
  if (name === 'delegate_task' || name === 'delegate_parallel') return 'delegation';
  if (name === 'escalate') return 'admin';
  if (
    name === 'bash'
    || name === 'read_file'
    || name === 'write_file'
    || name === 'list_dir'
    || name === 'find_files'
    || name === 'grep'
    || name === 'edit'
    || name === 'patch'
    || name === 'clarify'
  ) {
    return 'builtin';
  }
  return 'custom';
}

export function toToolExecutionMode(name: string): SubagentToolManifestItem['executionMode'] {
  return SEQUENTIAL_TOOLS.has(name) ? 'sequential' : 'parallel';
}

export function supportsWorkerExecution(name: string): boolean {
  return LOCAL_WORKER_TOOLS.has(name);
}

export function supportsMainProcessProxy(name: string): boolean {
  return MAIN_PROCESS_PROXY_TOOLS.has(name) || name.startsWith('mysql_');
}

export function requiresShell(name: string): boolean {
  return name === 'bash';
}

export function requiresWrite(name: string): boolean {
  return name === 'write_file' || name === 'edit' || name === 'patch' || name === 'memory_save';
}

export function requiresSkillScope(name: string): boolean {
  return name === 'read_skill' || name === 'read_skill_file' || name === 'skill_manage';
}

export function requiresWorkspaceRootForTool(name: string): boolean {
  return WORKSPACE_ROOT_TOOLS.has(name);
}

export function getBaseWorkerRoutingHint(name: string): NonNullable<SubagentToolManifestItem['workerRoutingHint']> {
  if (supportsWorkerExecution(name)) return 'local';
  if (supportsMainProcessProxy(name)) return 'main-process-proxy';
  return 'disabled';
}

export function applyWorkerRoutingStrategy(
  base: NonNullable<SubagentToolManifestItem['workerRoutingHint']>,
  strategy: ToolWorkerRoutingStrategy | undefined
): NonNullable<SubagentToolManifestItem['workerRoutingHint']> {
  if (strategy === 'force-local') return 'local';
  if (strategy === 'force-main-process-proxy') return 'main-process-proxy';
  if (strategy === 'force-disabled') return 'disabled';
  return base;
}

export function buildToolRuntimeProfile(
  name: string,
  extra?: ToolGovernanceExtra | null
): ToolRuntimeProfile {
  const workerRoutingHint = applyWorkerRoutingStrategy(
    getBaseWorkerRoutingHint(name),
    extra?.workerRoutingStrategy
  );

  return {
    kind: toToolKind(name),
    executionMode: toToolExecutionMode(name),
    supportedInWorker: workerRoutingHint === 'local',
    workerRoutingHint,
    requiresShell: requiresShell(name) || undefined,
    requiresWrite: requiresWrite(name) || undefined,
    requiresSkillScope: requiresSkillScope(name) || undefined,
  };
}

export function buildToolManifestItem(
  name: string,
  config?: ToolManifestConfig | null,
  extra?: ToolGovernanceExtra | null
): SubagentToolManifestItem {
  return {
    name,
    visibility: (config?.visibility as SubagentToolManifestItem['visibility']) ?? 'tool',
    capability: (config?.capability as SubagentToolManifestItem['capability']) ?? 'text',
    ...buildToolRuntimeProfile(name, extra),
  };
}
