import { AgentRunner, type AgentResult } from './runner.js';
import { ToolRegistry } from './tools/registry.js';
import { loadConfig } from '../config.js';
import { createLogger, type Logger } from '../utils/logger.js';
import type { SubAgentType, ModelTier } from './tools/task.js';

// Import tools for registry setup
import { readFileTool, listFilesTool } from './tools/coding.js';
import { grepTool, globTool } from './tools/search.js';
import { writeFileTool } from './tools/coding.js';
import { executeCommandTool, gitCommandTool } from './tools/shell.js';

/**
 * Tool allowlists per agent type
 */
const TOOL_ALLOWLIST: Record<SubAgentType, string[]> = {
  explore: ['read_file', 'list_files', 'grep', 'glob'],
  plan: ['read_file', 'list_files', 'grep', 'glob', 'write_file'],
  bash: ['execute_command', 'git_command', 'read_file'],
};

/**
 * Model tier to actual model mapping
 */
const MODEL_TIERS: Record<ModelTier, string> = {
  fast: 'claude-3-5-haiku-20241022',
  standard: 'claude-sonnet-4-20250514',
  powerful: 'claude-opus-4-20250514',
};

/**
 * Max iterations per agent type
 */
const MAX_ITERATIONS: Record<SubAgentType, number> = {
  explore: 20,
  plan: 30,
  bash: 10,
};

export interface SubAgentResult {
  success: boolean;
  response: string;
  findings?: string[];
  filesExplored?: string[];
  toolCalls?: number;
  error?: string;
}

export interface SubAgentRunnerOptions {
  type: SubAgentType;
  repoRoot: string;
  model?: ModelTier;
  logger?: Logger;
}

/**
 * Lightweight sub-agent runner for focused tasks
 *
 * Sub-agents have restricted tool access and lower iteration limits.
 */
export class SubAgentRunner {
  private type: SubAgentType;
  private repoRoot: string;
  private model: string;
  private logger: Logger;

  constructor(options: SubAgentRunnerOptions) {
    this.type = options.type;
    this.repoRoot = options.repoRoot;
    this.model = MODEL_TIERS[options.model ?? 'standard'];
    this.logger = options.logger ?? createLogger({ name: `subagent-${options.type}` });
  }

  /**
   * Run the sub-agent synchronously
   */
  async run(prompt: string): Promise<SubAgentResult> {
    const config = loadConfig();

    // Create restricted tool registry
    const registry = this.createToolRegistry();

    const runner = new AgentRunner({
      config,
      logger: this.logger,
      repoRoot: this.repoRoot,
      model: this.model,
      mode: this.type === 'explore' ? 'explore' : this.type === 'plan' ? 'plan' : 'code',
      maxIterations: MAX_ITERATIONS[this.type],
      tools: registry,
    });

    try {
      this.logger.info({ type: this.type, model: this.model }, 'Starting sub-agent');

      const result = await runner.run(prompt);

      return {
        success: true,
        response: result.response,
        filesExplored: this.extractFilesExplored(result),
        findings: this.extractFindings(result),
        toolCalls: result.toolCalls.length,
      };
    } catch (err) {
      this.logger.error({ error: err }, 'Sub-agent failed');
      return {
        success: false,
        response: '',
        error: String(err),
      };
    }
  }

  /**
   * Start the sub-agent in background
   *
   * @returns Task ID for status checking
   */
  async startBackground(prompt: string): Promise<string> {
    // Generate task ID
    const taskId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;

    // Run in background (fire and forget for now)
    // In a full implementation, this would use a task queue or worker
    this.run(prompt).catch((err) => {
      this.logger.error({ taskId, error: err }, 'Background task failed');
    });

    return taskId;
  }

  /**
   * Create a tool registry with only allowed tools
   */
  private createToolRegistry(): ToolRegistry {
    const registry = new ToolRegistry();
    const allowedTools = TOOL_ALLOWLIST[this.type];

    // Map tool names to tool definitions
    const toolMap: Record<string, typeof readFileTool> = {
      read_file: readFileTool,
      list_files: listFilesTool,
      grep: grepTool,
      glob: globTool,
      write_file: writeFileTool,
      execute_command: executeCommandTool,
      git_command: gitCommandTool,
    };

    for (const name of allowedTools) {
      const tool = toolMap[name];
      if (tool) {
        registry.register(tool);
      }
    }

    return registry;
  }

  /**
   * Extract file paths from tool calls
   */
  private extractFilesExplored(result: AgentResult): string[] {
    const files = new Set<string>();

    for (const call of result.toolCalls) {
      if (call.name === 'read_file' || call.name === 'list_files') {
        const path = (call.input as { path?: string }).path;
        if (path) {
          files.add(path);
        }
      }
    }

    return Array.from(files);
  }

  /**
   * Extract key findings from the response
   *
   * Simple implementation - looks for bullet points or numbered lists
   */
  private extractFindings(result: AgentResult): string[] {
    const findings: string[] = [];
    const lines = result.response.split('\n');

    for (const line of lines) {
      // Match bullet points or numbered items
      const match = line.match(/^[\s]*[-*•]\s+(.+)$/) || line.match(/^[\s]*\d+\.\s+(.+)$/);
      if (match) {
        findings.push(match[1].trim());
      }
    }

    // Limit to first 10 findings
    return findings.slice(0, 10);
  }
}
