/** Task tools — the background-task lifecycle (list / inspect / create / cancel /
 *  delete). Calls lib/task-manager in-process. */

import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import {
  listTasksLite, getTask, createTask, cancelTask,
} from '@/lib/task-manager';
import { getProjectInfo } from '@/lib/projects';
import { ensureInitialized } from '@/lib/init';
import type { TaskStatus } from '@/src/types';
import { text, fail, guard, describeSession } from './_shared';

const STATUS = ['queued', 'running', 'done', 'failed', 'cancelled'] as const;
const ICON: Record<string, string> = { queued: '⏳', running: '🔄', done: '✅', failed: '❌', cancelled: '⚪' };

export function registerTaskTools(server: McpServer): void {
  server.tool(
    'forge_list_tasks',
    'List background tasks, newest first. Optionally filter by status. Returns id, status, project, prompt, and cost — use forge_get_task for full detail.',
    { status: z.enum(STATUS).optional().describe('Filter by status') },
    (params) => guard(() => {
      const tasks = listTasksLite(params.status as TaskStatus | undefined);
      if (tasks.length === 0) return text(params.status ? `No ${params.status} tasks.` : 'No tasks.');
      const lines = tasks.slice(0, 50).map((t) => {
        const cost = t.costUSD != null ? ` $${t.costUSD.toFixed(3)}` : '';
        return `${ICON[t.status] || '?'} ${t.id}  ${t.status.padEnd(9)} ${t.projectName}  ${t.prompt.slice(0, 60)}${cost}`;
      });
      const more = tasks.length > 50 ? `\n… ${tasks.length - 50} more` : '';
      return text(`${tasks.length} task(s):\n${lines.join('\n')}${more}`);
    }),
  );

  server.tool(
    'forge_get_task',
    'Get full detail for one task: status, prompt, cost, result summary, error, and git branch.',
    { id: z.string().describe('Task id') },
    (params) => guard(() => {
      const t = getTask(params.id);
      if (!t) return fail(`Task not found: ${params.id}`);
      const lines = [
        `${ICON[t.status] || '?'} Task ${t.id} [${t.status}]`,
        `Project: ${t.projectName} (${t.projectPath})`,
        `Prompt: ${t.prompt}`,
      ];
      if (t.agent) lines.push(`Agent: ${t.agent}`);
      if (t.gitBranch) lines.push(`Branch: ${t.gitBranch}`);
      if (t.costUSD != null) lines.push(`Cost: $${t.costUSD.toFixed(4)}`);
      if (t.startedAt) lines.push(`Started: ${t.startedAt}`);
      if (t.completedAt) lines.push(`Completed: ${t.completedAt}`);
      if (t.error) lines.push(`\nError: ${t.error}`);
      if (t.resultSummary) lines.push(`\nResult:\n${t.resultSummary.slice(0, 1500)}`);
      return text(lines.join('\n'));
    }),
  );

  server.tool(
    'forge_create_task',
    'Submit a background task to run an agent in a project. Resolves the project by name (see forge_list_projects). By default it continues the project\'s existing session; set new_session to start fresh.',
    {
      project: z.string().describe('Project name (from forge_list_projects)'),
      prompt: z.string().describe('What the agent should do'),
      new_session: z.boolean().optional().describe('Start a fresh session instead of continuing the project\'s last one'),
      agent: z.string().optional().describe('Agent/CLI to use (e.g. "claude", "codex"); defaults to the configured agent'),
    },
    (params) => guard(() => {
      const project = getProjectInfo(params.project);
      if (!project) return fail(`Project not found: ${params.project}. Use forge_list_projects to see valid names.`);
      ensureInitialized(); // make sure the task runner is up so the task actually executes
      const task = createTask({
        projectName: project.name,
        projectPath: project.path,
        prompt: params.prompt,
        priority: 0,
        conversationId: params.new_session ? '' : undefined,
        mode: 'prompt',
        agent: params.agent || undefined,
      });
      const session = describeSession(params.new_session, task.conversationId);
      return text(`Created task ${task.id} in ${task.projectName} (${session}).\nPrompt: ${params.prompt}\nInspect with forge_get_task id=${task.id}.`);
    }),
  );

  server.tool(
    'forge_cancel_task',
    'Cancel a queued or running task. Does not delete it — its record and partial output remain.',
    { id: z.string().describe('Task id') },
    (params) => guard(() => {
      const ok = cancelTask(params.id);
      return text(ok ? `Cancelled task ${params.id}.` : `Could not cancel ${params.id} (not found, or already finished).`);
    }),
  );
}
