import { existsSync } from 'node:fs';
import { join } from 'node:path';
import { ToolDef } from '../../llm/openai-compat.js';
import { ToolContext, ToolResult } from './core.js';

export const TOOL_DEFS: Record<string, ToolDef> = {
  delegate: {
    type: 'function',
    function: {
      name: 'delegate',
      description: 'サブエージェントに作業を委譲し、その最終結果だけを受け取ります（中間作業はあなたの文脈に残りません）。重い調査・分解作業を文脈を節約しつつ任せたいときに使用。直列実行（同時に1つ）。詳細は ReadToolDoc({ name: "delegate" })。',
      parameters: {
        type: 'object',
        properties: {
          description: { type: 'string', description: '委譲タスクの短い説明（3-6語）' },
          prompt: { type: 'string', description: 'サブエージェントへの完全な指示。サブは独立した文脈で動くため、必要な背景を自己完結で書く' },
        },
        required: ['description', 'prompt'],
      },
    },
  },
  SpawnSubTask: {
    type: 'function',
    function: {
      name: 'SpawnSubTask',
      description: 'サブタスクを作成してキューに追加します。分解した調査項目などを並列実行したい場合に使用します。複数回呼び出すことで複数のサブタスクを並列スケジュールできます。分解判断・instruction の書き方は ReadToolDoc({ name: "SpawnSubTask" })。',
      parameters: {
        type: 'object',
        properties: {
          title: {
            type: 'string',
            description: 'サブタスクのタイトル（簡潔に）',
          },
          instruction: {
            type: 'string',
            description: 'サブタスクへの詳細な指示。何を調査・実行してほしいか、どんな形式で output/ に結果を書いてほしいかを具体的に記述する。',
          },
          piece: {
            type: 'string',
            description: '使用するピース名（general, research, brainstorming, data-process, office-process）。デフォルトは general。',
          },
        },
        required: ['title', 'instruction'],
      },
    },
  },
  WaitSubTask: {
    type: 'function',
    function: {
      name: 'WaitSubTask',
      description: 'SpawnSubTask で起動した全サブタスクの完了を待ちます（引数なし）。並列起動したあとに1回呼ぶと全完了まで停車し、完了後に subtasks/ へ結果が揃った状態で同じステップに再開します。詳細は ReadToolDoc({ name: "SpawnSubTask" })。',
      parameters: {
        type: 'object',
        properties: {},
        required: [],
      },
    },
  },
};

export async function executeTool(
  name: string,
  input: Record<string, unknown>,
  ctx: ToolContext,
): Promise<ToolResult | null> {
  if (name !== 'SpawnSubTask' && name !== 'delegate' && name !== 'WaitSubTask') return null;

  if (name === 'WaitSubTask') {
    if (!ctx.hasPendingSubtasks) {
      return { output: 'WaitSubTask はこのコンテキストでは使用できません（サブタスク非対応の実行経路）。', isError: true };
    }
    const hasPending = await ctx.hasPendingSubtasks();
    if (!hasPending) {
      return {
        output: '待機対象の未完了サブタスクはありません。subtasks/ 配下の各 result.md を読んで統合し、回答を complete してください。SpawnSubTask を再度呼ぶ必要はありません。',
        isError: false,
      };
    }
    // 制御フロー（park シグナル）: agent-loop がこのフラグを見て movement を
    // WAIT_SUBTASKS で停車させ、同じ movement に再開する。ツール内で同期ブロックは
    // しない（ワーカー解放を保つ＝デッドロック回避）。
    ctx.pendingSubtaskWait = true;
    return {
      output: 'サブタスクの完了を待機します。全完了後、同じステップに再開し、subtasks/ の結果を読めます。',
      isError: false,
    };
  }

  if (name === 'delegate') {
    if (!ctx.runDelegate) {
      return { output: 'delegate はこのコンテキストでは使用できません（ネスト上限、または未対応の実行経路）。', isError: true };
    }
    const description = typeof input['description'] === 'string' ? input['description'] : '';
    const prompt = typeof input['prompt'] === 'string' ? input['prompt'] : '';
    if (!prompt.trim()) return { output: 'delegate: prompt が空です。', isError: true };
    try {
      const { result, status } = await ctx.runDelegate({ description, prompt });
      if (status === 'aborted') return { output: `[delegate 中断] ${result}`, isError: true };
      if (status === 'needs_user_input') return { output: `[delegate 要追加情報] ${result}`, isError: false };
      return { output: result, isError: false };
    } catch (err) {
      return { output: `delegate 失敗: ${err instanceof Error ? err.message : String(err)}`, isError: true };
    }
  }

  const { spawnSubTask } = ctx;
  if (!spawnSubTask) {
    return { output: 'SpawnSubTask はこのコンテキストでは使用できません', isError: true };
  }

  const title = typeof input['title'] === 'string' ? input['title'].trim() : '';
  const instruction = typeof input['instruction'] === 'string' ? input['instruction'].trim() : '';
  const piece = typeof input['piece'] === 'string' ? input['piece'] : 'general';

  if (!title || !instruction) {
    return { output: 'title と instruction は必須です', isError: true };
  }

  const builtinPath = join('pieces', `${piece}.yaml`);
  const customDirs = ctx.customPiecesDir
    ? (Array.isArray(ctx.customPiecesDir) ? ctx.customPiecesDir : [ctx.customPiecesDir])
    : [];
  const customExists = customDirs.some(d => existsSync(join(d, `${piece}.yaml`)));
  if (!existsSync(builtinPath) && !customExists) {
    return {
      output: `指定されたピース "${piece}" が見つかりません。利用可能なピースを確認してください。`,
      isError: true,
    };
  }

  try {
    const result = await spawnSubTask({ title, instruction, piece });
    return {
      output: [
        `サブタスク #${result.subtaskIndex} を登録しました。`,
        `タイトル: ${title}`,
        `ジョブ ID: ${result.jobId}`,
        `ワークスペース: ${result.workspacePath}`,
      ].join('\n'),
      isError: false,
    };
  } catch (err) {
    return {
      output: `SpawnSubTask 失敗: ${err instanceof Error ? err.message : String(err)}`,
      isError: true,
    };
  }
}
