/** Workspace-agent tools — add/list the agents ("smiths") in a project's
 *  multi-agent workspace (e.g. add a code reviewer). These are DISTINCT from CLI
 *  agents (see integrations.ts).
 *
 *  Per the single-writer rule, workspace mutations go through the workspace daemon
 *  HTTP API (never direct state.json writes). Reads use in-process lib. */

import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { getProjectInfo } from '@/lib/projects';
import { findWorkspaceByProject } from '@/lib/workspace';
import { createFromPreset, AGENT_PRESETS } from '@/lib/workspace/presets';
import { text, fail, guard } from './_shared';

const DAEMON = `http://localhost:${Number(process.env.WORKSPACE_PORT) || 8405}`;

/** Map a natural-language role to a preset key (presets: pm, architect, engineer, qa, reviewer, lead). */
function resolveRole(input: string): string | undefined {
  const q = input.toLowerCase().replace(/[\s_-]+/g, '');
  const alias: Record<string, string> = {
    codereviewer: 'reviewer', reviewer: 'reviewer', review: 'reviewer',
    engineer: 'engineer', dev: 'engineer', developer: 'engineer', coder: 'engineer',
    qa: 'qa', tester: 'qa', test: 'qa',
    pm: 'pm', productmanager: 'pm', product: 'pm',
    architect: 'architect', arch: 'architect',
    lead: 'lead', techlead: 'lead',
  };
  const key = alias[q] || q;
  return AGENT_PRESETS[key] ? key : undefined;
}

async function daemon(path: string, body: unknown): Promise<{ ok: boolean; data?: any; error?: string }> {
  try {
    const res = await fetch(`${DAEMON}${path}`, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(body),
    });
    const data = await res.json().catch(() => ({}));
    if (!res.ok) return { ok: false, error: data?.error || `daemon returned ${res.status}` };
    return { ok: true, data };
  } catch (e) {
    return { ok: false, error: `workspace daemon unreachable at ${DAEMON} (${(e as Error).message}). Is Forge fully started?` };
  }
}

export function registerWorkspaceTools(server: McpServer): void {
  server.tool(
    'forge_list_workspace_agents',
    'List the agents (smiths) in a project\'s multi-agent workspace and their roles.',
    { project: z.string().describe('Project name') },
    (params) => guard(() => {
      const project = getProjectInfo(params.project);
      if (!project) return fail(`Project not found: ${params.project}. Use forge_list_projects.`);
      const ws = findWorkspaceByProject(project.path);
      if (!ws) return text(`No workspace exists for ${project.name} yet. Add an agent with forge_add_workspace_agent to create one.`);
      const agents = (ws.agents || []).filter((a) => a.type !== 'input');
      if (agents.length === 0) return text(`${project.name}'s workspace has no agents yet.`);
      const lines = agents.map((a) => `• ${a.label} (${a.role ? a.role.slice(0, 60) : a.backend})${a.primary ? ' [primary]' : ''}`);
      return text(`${agents.length} workspace agent(s) in ${project.name}:\n${lines.join('\n')}`);
    }),
  );

  server.tool(
    'forge_add_workspace_agent',
    'Add an agent to a project\'s multi-agent workspace by role (e.g. "code reviewer", "engineer", "qa", "architect", "pm", "lead"). Creates the workspace if needed. Goes through the workspace daemon.',
    {
      project: z.string().describe('Project name (from forge_list_projects)'),
      role: z.string().describe('Role to add, e.g. "code reviewer", "engineer", "qa"'),
    },
    (params) => guard(async () => {
      const project = getProjectInfo(params.project);
      if (!project) return fail(`Project not found: ${params.project}. Use forge_list_projects.`);
      const roleKey = resolveRole(params.role);
      if (!roleKey) return fail(`Unknown role "${params.role}". Available: ${Object.keys(AGENT_PRESETS).join(', ')}.`);

      // Find or create the workspace (create goes through the daemon — single writer).
      // findWorkspaceByProject is typed (WorkspaceState.id); the daemon response is
      // untrusted HTTP, so narrow it to the one field we use rather than `any`.
      let wsId = findWorkspaceByProject(project.path)?.id;
      if (!wsId) {
        const created = await daemon('/workspace/create', { projectPath: project.path, projectName: project.name });
        if (!created.ok) return fail(created.error || 'Could not create workspace.');
        wsId = (created.data as { id?: string } | undefined)?.id;
      }
      if (!wsId) return fail('Could not resolve workspace id.');

      const config = createFromPreset(roleKey);
      const added = await daemon(`/workspace/${wsId}/agents`, { action: 'add', config });
      if (!added.ok) return fail(added.error || 'Could not add agent.');
      return text(`Added ${config.label} (${roleKey}) to ${project.name}'s workspace.`);
    }),
  );
}
