/**
 * BuiltInToolRegistrar - Registers all built-in tools into ToolRegistry
 *
 * Implements T-214: Registers T-206..T-213 tools into ToolRegistry
 *
 * @module packages/runtime/src/tools/BuiltInToolRegistrar
 */

import { ToolRegistry } from './ToolRegistry.js'
import { fs_read, fs_write, fs_edit, fs_patch, fs_list, createFsExecutors } from './fs/index.js'
import { shell_run, createShellExecutor } from './shell/index.js'
import { git_status, git_diff, git_commit, git_branch, git_merge, createGitExecutor } from './git/index.js'
import { project_rules, project_context, createProjectExecutor } from './project/index.js'
import { artifact_create, artifact_read, createArtifactExecutor } from './artifact/index.js'
import { context_assemble, context_compact, createContextExecutor } from './context/index.js'
import { permission_check, permission_prompt, createPermissionExecutor } from './permission/index.js'
import { doctor_check, doctor_fix, createDoctorExecutor } from './doctor/index.js'

/**
 * Register all built-in tools into a ToolRegistry instance.
 */
export class BuiltInToolRegistrar {
  private registry: ToolRegistry

  constructor(registry: ToolRegistry) {
    this.registry = registry
  }

  /**
   * Register all built-in tools.
   */
  register_all(project_root: string): void {
    // FS Tools (T-206)
    this.register_tool(fs_read, createFsExecutors(project_root)['fs.read'])
    this.register_tool(fs_write, createFsExecutors(project_root)['fs.write'])
    this.register_tool(fs_edit, createFsExecutors(project_root)['fs.edit'])
    this.register_tool(fs_patch, createFsExecutors(project_root)['fs.patch'])
    this.register_tool(fs_list, createFsExecutors(project_root)['fs.list'])

    // Shell Tool (T-207)
    this.register_tool(shell_run, createShellExecutor(project_root)['shell.run'])

    // Git Tools (T-208)
    this.register_tool(git_status, createGitExecutor(project_root)['git.status'])
    this.register_tool(git_diff, createGitExecutor(project_root)['git.diff'])
    this.register_tool(git_commit, createGitExecutor(project_root)['git.commit'])
    this.register_tool(git_branch, createGitExecutor(project_root)['git.branch'])
    this.register_tool(git_merge, createGitExecutor(project_root)['git.merge'])

    // Project Tools (T-209)
    this.register_tool(project_rules, createProjectExecutor(project_root)['project.rules'])
    this.register_tool(project_context, createProjectExecutor(project_root)['project.context'])

    // Artifact Tools (T-210)
    this.register_tool(artifact_create, createArtifactExecutor()['artifact.create'])
    this.register_tool(artifact_read, createArtifactExecutor()['artifact.read'])

    // Context Tools (T-211)
    this.register_tool(context_assemble, createContextExecutor()['context.assemble'])
    this.register_tool(context_compact, createContextExecutor()['context.compact'])

    // Permission Tools (T-212)
    this.register_tool(permission_check, createPermissionExecutor()['permission.check'])
    this.register_tool(permission_prompt, createPermissionExecutor()['permission.prompt'])

    // Doctor Tools (T-213)
    this.register_tool(doctor_check, createDoctorExecutor()['doctor.check'])
    this.register_tool(doctor_fix, createDoctorExecutor()['doctor.fix'])

    // Stub Tools - high-priority registrations (Alpha scope)
    const stub_definitions = this.create_stub_definitions()
    for (const [name, definition] of Object.entries(stub_definitions)) {
      this.register_tool(definition as any, this.create_stub_executor(name))
    }
  }

  /**
   * Register a single tool with its executor.
   */
  private register_tool(definition: typeof fs_read, executor: (call: any) => any): void {
    this.registry.register(definition.name, definition, executor)
  }

  /**
   * Create stub tool definitions for high-priority tools (Alpha scope).
   */
  private create_stub_definitions(): Record<string, typeof fs_read> {
    const def = (name: string, category: string, desc: string, props: Record<string,unknown> = {}, required: string[] = [], perms = { read: true, write: false, network: false }) => ({
      name, category, description: desc,
      input_schema: { type: 'object', properties: props, required },
      permissions: perms, streaming: false
    })

    return {
      // fs
      'fs.stat': def('fs.stat', 'filesystem', 'Get filesystem stat info for a path',
        { path: { type: 'string', description: 'File or directory path to stat' } }, ['path']),
      // process
      'process.kill': def('process.kill', 'shell', 'Terminate a child process by PID or signal',
        { pid: { type: 'number', description: 'Process ID to terminate' }, signal: { type: 'string', description: 'Signal (TERM/KILL)' } }, ['pid'],
        { read: false, write: false, network: false }),
      // git worktree
      'git.worktree.create': def('git.worktree.create', 'git', 'Create a git worktree for isolated task execution',
        { path: { type: 'string', description: 'Path for new worktree' }, base_ref: { type: 'string', description: 'Base ref (branch/tag/commit)' } }, ['path'],
        { read: false, write: true, network: false }),
      'git.merge_workspace': def('git.merge_workspace', 'git', 'Merge worktree changes back into main branch',
        { workspace_id: { type: 'string', description: 'Workspace ID to merge' }, strategy: { type: 'string', description: 'Merge strategy (merge/rebase/fast_forward)' } }, ['workspace_id'],
        { read: false, write: true, network: false }),
      // project
      'project.scan': def('project.scan', 'project', 'Scan project directory for source files, builds, and toolchains',
        { root: { type: 'string', description: 'Project root to scan' }, depth: { type: 'number', description: 'Scan depth' } }, [],
        { read: true, write: false, network: false }),
      'project.profile.write': def('project.profile.write', 'project', 'Write language profile/toolchain configuration',
        { language: { type: 'string', description: 'Language (cpp/c/rust/python)' }, profile_json: { type: 'object', description: 'Profile configuration' } }, ['language', 'profile_json'],
        { read: false, write: true, network: false }),
      // cpp toolchain
      'cpp.detect': def('cpp.detect', 'debug', 'Detect C++ project structure, toolchain, and source files',
        { project_root: { type: 'string', description: 'Project root path' } }, []),
      'cpp.cmake.configure': def('cpp.cmake.configure', 'build', 'Configure C++ build with CMake (Ninja preferred, Make fallback)',
        { generator: { type: 'string', description: 'Generator (Ninja/Unix Makefiles)' }, build_type: { type: 'string', description: 'Debug/Release/RelWithDebInfo' } }, [],
        { read: true, write: true, network: false }),
      'cpp.build': def('cpp.build', 'build', 'Build C++ project via CMake',
        { target: { type: 'string', description: 'Build target' }, config: { type: 'string', description: 'Debug/Release' } }, []),
      'cpp.test': def('cpp.test', 'test', 'Run C++ tests via ctest',
        { filter: { type: 'string', description: 'Test filter pattern' } }, []),
      'cpp.static.cppcheck': def('cpp.static.cppcheck', 'static_analysis', 'Run cppcheck static analysis on C++ code',
        { path: { type: 'string', description: 'Path to analyze' }, severity: { type: 'string', description: 'Minimum severity' } }, []),
      'cpp.clangd.query': def('cpp.clangd.query', 'static_analysis', 'Query clangd LSP for symbol definition or diagnostics',
        { file: { type: 'string', description: 'Source file path' }, line: { type: 'number', description: 'Line number' }, column: { type: 'number', description: 'Column number' } }, ['file']),
      // debug
      'debug.run': def('debug.run', 'debug', 'Run debugger on a target process or binary',
        { target: { type: 'string', description: 'Binary or process to debug' }, breakpoints: { type: 'array', items: { type: 'string' } } }, ['target']),
      'debug.parse_logs': def('debug.parse_logs', 'debug', 'Parse debug/crash log output into structured diagnostics',
        { log_path: { type: 'string', description: 'Path to log file' }, format: { type: 'string', description: 'Log format (gdb/lldb/valgrind/asan)' } }, ['log_path']),
      // gui evidence
      'gui.screenshot': def('gui.screenshot', 'gui', 'Capture a screenshot of the current GUI state for evidence',
        { window_title: { type: 'string', description: 'Target window title (partial match)' }, region: { type: 'object', description: '{x,y,w,h} capture region' } }, []),
      // network evidence
      'network.capture': def('network.capture', 'network', 'Capture network traffic for evidence (tcpdump/tshark wrapper)',
        { interface: { type: 'string', description: 'Network interface' }, duration_sec: { type: 'number', description: 'Capture duration in seconds' }, filter: { type: 'string', description: 'BPF/tcpdump filter expression' } }, [],
        { read: false, write: false, network: true }),
      // permission
      'permission.request': def('permission.request', 'permission', 'Request user permission for an action (blocking prompt)',
        { tool_name: { type: 'string', description: 'Tool to request permission for' }, reason: { type: 'string', description: 'Why permission is needed' } }, ['tool_name', 'reason']),
      // doctor
      'doctor.run': def('doctor.run', 'doctor', 'Run full diagnostic suite (self-bootstrap + capability + project)',
        { scope: { type: 'string', description: 'all/self_bootstrap/capability/project' }, fix: { type: 'boolean', description: 'Attempt automatic fixes' } }, [],
        { read: true, write: false, network: false }),
    }
  }

  /**
   * Create a stub executor that returns a structured not_implemented result.
   */
  private create_stub_executor(tool_name: string): (call: any) => Promise<any> {
    return async (call: any) => ({
      call_id: call.id || '',
      tool_name,
      type: 'text',
      content: { message: `Tool ${tool_name} not yet implemented (Alpha scope)` },
      metadata: { timestamp: new Date().toISOString(), alpha_stub: true }
    })
  }

}

export function register_builtin_tools(registry: ToolRegistry, project_root: string): BuiltInToolRegistrar {
  const registrar = new BuiltInToolRegistrar(registry)
  registrar.register_all(project_root)
  return registrar
}