/**
 * Background Task Tools
 *
 * Tools for managing background tasks (shell commands and sub-agents)
 * that run asynchronously.
 */

import { z } from 'zod';
import { defineTool, type ToolResult } from './types.js';
import {
  BackgroundTaskManager,
  type BackgroundTask,
  type BackgroundTaskInfo,
  type BackgroundTaskStatus,
} from '../background.js';

/**
 * Task Output Tool
 *
 * Get output from a running or completed background task.
 */
export const taskOutputTool = defineTool({
  name: 'task_output',
  description: `Get output from a background task (shell command or sub-agent).

Use this to check the status and results of tasks started with run_in_background=true.
Can wait for completion or check immediately.

Works with:
- Shell commands: execute_command(..., run_in_background=true)
- Sub-agents: task(..., background=true)`,
  category: 'task',
  schema: z.object({
    task_id: z.string().min(1).describe('Task ID to get output from (e.g., shell_abc123 or agent_xyz789)'),
    block: z.boolean().optional().default(true).describe('Wait for completion (default: true)'),
    timeout: z.number().int().min(1).max(600).optional().default(60).describe('Max wait time in seconds if blocking'),
  }),
  async execute(input): Promise<ToolResult<BackgroundTaskInfo & { message?: string }>> {
    const { task_id, block = true, timeout = 60 } = input;

    const manager = BackgroundTaskManager.getInstance();
    const task = manager.getTask(task_id);

    if (!task) {
      return {
        success: false,
        error: `Task ${task_id} not found`,
        suggestions: ['Check the task_id is correct', 'Use list_tasks to see all tasks'],
      };
    }

    // If blocking and task is running, wait for completion
    if (block && task.status === 'running') {
      const startTime = Date.now();
      const timeoutMs = timeout * 1000;

      while (Date.now() - startTime < timeoutMs) {
        if (task.status !== 'running') {
          break;
        }
        await sleep(500);
      }

      // Check if still running after timeout
      if (task.status === 'running') {
        return {
          success: true,
          data: {
            ...manager.taskToInfo(task),
            message: `Task did not complete within ${timeout}s`,
          },
          suggestions: ['Use block=false to check status without waiting', 'Use a longer timeout'],
        };
      }
    }

    return {
      success: true,
      data: manager.taskToInfo(task),
    };
  },
});

/**
 * Kill Task Tool
 *
 * Kill a running background task.
 */
export const killTaskTool = defineTool({
  name: 'kill_task',
  description: `Kill a running background task (shell command or sub-agent).

Use this to terminate tasks that are no longer needed or are stuck.
Works with shell commands and sub-agents started with run_in_background=true.`,
  category: 'task',
  schema: z.object({
    task_id: z.string().min(1).describe('Task ID to kill'),
  }),
  async execute(input): Promise<ToolResult<{ task_id: string; killed: boolean; message: string }>> {
    const { task_id } = input;

    const manager = BackgroundTaskManager.getInstance();
    const task = manager.getTask(task_id);

    if (!task) {
      return {
        success: false,
        error: `Task ${task_id} not found`,
        suggestions: ['Check the task_id is correct', 'Use list_tasks to see all tasks'],
      };
    }

    if (task.status !== 'running') {
      return {
        success: false,
        error: `Task ${task_id} is not running (status: ${task.status})`,
      };
    }

    const success = manager.killTask(task_id);

    if (success) {
      return {
        success: true,
        data: {
          task_id,
          killed: true,
          message: `Task ${task_id} has been terminated`,
        },
      };
    } else {
      return {
        success: false,
        error: `Failed to kill task ${task_id}`,
      };
    }
  },
});

/**
 * List Tasks Tool
 *
 * List all background tasks.
 */
export const listTasksTool = defineTool({
  name: 'list_tasks',
  description: `List all background tasks (running and completed).

Shows status of all shell commands and sub-agents started with run_in_background=true.`,
  category: 'task',
  schema: z.object({
    status_filter: z.enum(['running', 'completed', 'failed', 'killed']).optional().describe('Filter by task status (optional)'),
  }),
  async execute(input): Promise<ToolResult<{
    tasks: Array<{
      task_id: string;
      type: string;
      status: string;
      description: string;
      command?: string;
      agent_type?: string;
      exit_code?: number;
    }>;
    total: number;
    running: number;
  }>> {
    const { status_filter } = input;

    const manager = BackgroundTaskManager.getInstance();
    let tasks = manager.getAllTasks();

    // Apply filter if provided
    if (status_filter) {
      tasks = tasks.filter((t) => t.status === status_filter);
    }

    // Format task list
    const taskList = tasks.map((task) => {
      const info: {
        task_id: string;
        type: string;
        status: string;
        description: string;
        command?: string;
        agent_type?: string;
        exit_code?: number;
      } = {
        task_id: task.taskId,
        type: task.taskType,
        status: task.status,
        description: task.description,
      };

      if (task.taskType === 'shell' && task.command) {
        info.command = task.command.length > 50 ? task.command.slice(0, 50) + '...' : task.command;
      } else if (task.agentType) {
        info.agent_type = task.agentType;
      }

      if (task.exitCode !== undefined) {
        info.exit_code = task.exitCode;
      }

      return info;
    });

    const allTasks = manager.getAllTasks();
    const runningCount = allTasks.filter((t) => t.status === 'running').length;

    return {
      success: true,
      data: {
        tasks: taskList,
        total: taskList.length,
        running: runningCount,
      },
    };
  },
});

/**
 * Helper: sleep for ms
 */
function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

/**
 * All background task tools
 */
export const backgroundTaskTools = [taskOutputTool, killTaskTool, listTasksTool];
