import { ToolDef } from '../../llm/openai-compat.js';
import type { ToolContext, ToolResult } from './core.js';
import { logger } from '../../logger.js';

// Brainstorm ツール (issue #247)
// =====================================================================
// 目的: LLM が「一直線」な思考に陥らないよう、着手前に複数アプローチを
// 構造化された形で列挙させる checkpoint を提供する。
//
// 設計判断:
// - 内部で別 LLM 呼び出しはしない (KISS、トークン節約)。LLM 自身が
//   approaches を列挙し、tool 側は受け取って **比較表として整形 + ログ化**
//   するだけ。
// - 行き詰まり時のリセット用途も兼ねるため、`context` フィールドで
//   「これまで何を試したか」を残せるようにする。
// - tool call 履歴に残るので、後から「どのアプローチを比較した上で
//   選んだか」を UI / activity log で追跡できる。

interface Approach {
  name: string;
  description: string;
  reliability?: 'high' | 'medium' | 'low';
  speed?: 'fast' | 'medium' | 'slow';
  prerequisites?: string;
  risks?: string;
}

const BRAINSTORM_DEF: ToolDef = {
  type: 'function',
  function: {
    name: 'Brainstorm',
    description:
      '着手前 or 行き詰まり時に複数アプローチを列挙して比較する構造化 checkpoint。最低 2 個 (推奨 3 個) のアプローチを並べ、確実性・速度・前提・リスクで比較してから 1 つ選ぶ。同じツールを連続失敗した時や、複雑な依頼で「最初の思いつきで突き進みそう」な時に呼ぶ。詳細は ReadToolDoc({ name: "Brainstorm" })。',
    parameters: {
      type: 'object',
      properties: {
        task: {
          type: 'string',
          description: '今解こうとしているサブ問題を 1 文で。例: "input/data.xlsx の中身を要約したい"',
        },
        context: {
          type: 'string',
          description: '(任意) これまで試した手段・失敗した内容など。行き詰まり時のリセット用途で記入',
        },
        approaches: {
          type: 'array',
          minItems: 2,
          maxItems: 5,
          description: '検討する解法の配列。2 個以上。各 approach は確実性・速度を主観で評価する',
          items: {
            type: 'object',
            properties: {
              name: { type: 'string', description: '解法の短い名前 (例: "ReadExcel 直接", "CSV エクスポート経由")' },
              description: { type: 'string', description: '1-2 文で具体的な手順' },
              reliability: { type: 'string', enum: ['high', 'medium', 'low'], description: '確実性 (副作用無し / 後戻り可能 = high)' },
              speed: { type: 'string', enum: ['fast', 'medium', 'slow'], description: '所要時間の概算' },
              prerequisites: { type: 'string', description: '(任意) 前提条件 / 必要なもの' },
              risks: { type: 'string', description: '(任意) 想定される失敗パターン' },
            },
            required: ['name', 'description'],
          },
        },
        chosen: {
          type: 'string',
          description: '採用するアプローチの name。approaches[].name のどれかと完全一致させる',
        },
        rationale: {
          type: 'string',
          description: '採用理由を 1-2 文。"確実性が一番高いから" 等、なぜ他案より優れるかを書く',
        },
      },
      required: ['task', 'approaches', 'chosen', 'rationale'],
    },
  },
};

export const TOOL_DEFS: Record<string, ToolDef> = {
  Brainstorm: BRAINSTORM_DEF,
};

function formatApproach(a: Approach, marked: boolean): string {
  const lines: string[] = [];
  const prefix = marked ? '✓ ' : '  ';
  lines.push(`${prefix}**${a.name}**${marked ? ' (採用)' : ''}`);
  lines.push(`    ${a.description}`);
  const tags: string[] = [];
  if (a.reliability) tags.push(`確実性: ${a.reliability}`);
  if (a.speed) tags.push(`速度: ${a.speed}`);
  if (tags.length > 0) lines.push(`    [${tags.join(' / ')}]`);
  if (a.prerequisites) lines.push(`    前提: ${a.prerequisites}`);
  if (a.risks) lines.push(`    リスク: ${a.risks}`);
  return lines.join('\n');
}

export async function executeTool(
  name: string,
  input: Record<string, unknown>,
  _ctx: ToolContext,
): Promise<ToolResult | null> {
  if (name !== 'Brainstorm') return null;

  const task = typeof input['task'] === 'string' ? input['task'].trim() : '';
  const context = typeof input['context'] === 'string' ? input['context'].trim() : '';
  const approaches = Array.isArray(input['approaches']) ? (input['approaches'] as Approach[]) : [];
  const chosen = typeof input['chosen'] === 'string' ? input['chosen'].trim() : '';
  const rationale = typeof input['rationale'] === 'string' ? input['rationale'].trim() : '';

  if (!task) {
    return { output: 'Brainstorm error: task は必須です', isError: true };
  }
  if (approaches.length < 2) {
    return { output: 'Brainstorm error: approaches は 2 個以上必要です (1 個だと比較になりません)', isError: true };
  }
  if (!chosen) {
    return { output: 'Brainstorm error: chosen (採用する approach 名) は必須です', isError: true };
  }
  if (!rationale) {
    return { output: 'Brainstorm error: rationale (採用理由) は必須です', isError: true };
  }
  const chosenMatch = approaches.find((a) => a && typeof a.name === 'string' && a.name.trim() === chosen);
  if (!chosenMatch) {
    return {
      output: `Brainstorm error: chosen="${chosen}" は approaches[].name のどれとも一致しません。候補: ${approaches.map((a) => a?.name).filter(Boolean).join(' / ')}`,
      isError: true,
    };
  }

  const lines: string[] = [];
  lines.push(`# Brainstorm: ${task}`);
  if (context) {
    lines.push('');
    lines.push(`## 背景 / これまでの試行`);
    lines.push(context);
  }
  lines.push('');
  lines.push(`## 検討した ${approaches.length} 個のアプローチ`);
  for (const a of approaches) {
    if (!a || typeof a !== 'object') continue;
    lines.push('');
    lines.push(formatApproach(a, a.name === chosen));
  }
  lines.push('');
  lines.push(`## 採用: ${chosen}`);
  lines.push(`理由: ${rationale}`);
  lines.push('');
  lines.push('続けて、採用したアプローチで実装に進んでください。');

  logger.debug(`[brainstorm] task="${task.slice(0, 60)}" approaches=${approaches.length} chosen="${chosen}"`);

  return { output: lines.join('\n'), isError: false };
}
