import { describe, it, expect, afterEach } from 'vitest';
import { TOOL_DEFS, executeTool, setMcpToolLookup } from './docs.js';

describe('docs tool (ReadToolDoc)', () => {
  it('exports ReadToolDoc definition', () => {
    expect(TOOL_DEFS).toHaveProperty('ReadToolDoc');
  });

  it('reads existing tool doc', async () => {
    const result = await executeTool('ReadToolDoc', { name: 'BrowseWeb' }, {
      workspacePath: '/tmp/test',
      editAllowed: false,
    });
    expect(result).not.toBeNull();
    expect(result!.isError).toBe(false);
    expect(result!.output).toContain('BrowseWeb');
  });

  it('returns error and lists available docs for unknown tool', async () => {
    const result = await executeTool('ReadToolDoc', { name: 'NonExistent' }, {
      workspacePath: '/tmp/test',
      editAllowed: false,
    });
    expect(result!.isError).toBe(true);
    expect(result!.output).toContain('利用可能なドキュメント');
    expect(result!.output).toContain('browseweb');
  });

  it('rejects path traversal attempts', async () => {
    const result = await executeTool('ReadToolDoc', { name: '../../etc/passwd' }, {
      workspacePath: '/tmp/test',
      editAllowed: false,
    });
    expect(result!.isError).toBe(true);
    expect(result!.output).toContain('不正なツール名');
  });

  it('rejects empty name', async () => {
    const result = await executeTool('ReadToolDoc', {}, {
      workspacePath: '/tmp/test',
      editAllowed: false,
    });
    expect(result!.isError).toBe(true);
    expect(result!.output).toContain('name パラメータが必要');
  });

  it('returns null for unknown tool name', async () => {
    const result = await executeTool('SomeOtherTool', {}, {
      workspacePath: '/tmp/test',
      editAllowed: false,
    });
    expect(result).toBeNull();
  });
});

describe('ReadToolDoc MCP fallback', () => {
  afterEach(() => {
    setMcpToolLookup(null);
  });

  it('returns description + schema when lookup hits', async () => {
    setMcpToolLookup((serverId, toolName) => {
      if (serverId === 'canva' && toolName === 'create_design') {
        return {
          description: 'Create a Canva design',
          input_schema: JSON.stringify({ type: 'object', properties: { title: { type: 'string' } } }),
        };
      }
      return null;
    });
    const result = await executeTool('ReadToolDoc', { name: 'mcp__canva__create_design' }, {} as never);
    expect(result?.isError).toBe(false);
    expect(result?.output).toContain('Create a Canva design');
    expect(result?.output).toContain('Input schema');
    expect(result?.output).toContain('"title"');
  });

  it('returns benign error when MCP subsystem is not initialised', async () => {
    setMcpToolLookup(null);
    const result = await executeTool('ReadToolDoc', { name: 'mcp__canva__x' }, {} as never);
    expect(result?.isError).toBe(true);
    expect(result?.output).toContain('初期化されていません');
  });

  it('returns not-found when lookup returns null', async () => {
    setMcpToolLookup(() => null);
    const result = await executeTool('ReadToolDoc', { name: 'mcp__canva__unknown_tool' }, {} as never);
    expect(result?.isError).toBe(false);
    expect(result?.output).toContain('キャッシュ情報がありません');
  });

  it('rejects invalid MCP tool name', async () => {
    setMcpToolLookup(() => null);
    const result = await executeTool('ReadToolDoc', { name: 'mcp__bad' }, {} as never);
    expect(result?.isError).toBe(true);
    expect(result?.output).toContain('不正な MCP ツール名');
  });
});
