/**
 * T13: HTTP Transport Tests
 *
 * Tests for:
 * - registerAllTools registers correct tool count
 * - applyToolGating filters by category
 * - Write tools use getVaultPath() getter (not captured string)
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

// Import write tool registration functions to verify getter pattern
import { registerMutationTools } from '../../../src/tools/write/mutations.js';
import { registerTaskTools } from '../../../src/tools/write/tasks.js';
import { registerFrontmatterTools } from '../../../src/tools/write/frontmatter.js';
import { registerNoteTools } from '../../../src/tools/write/notes.js';
import { registerMoveNoteTools } from '../../../src/tools/write/move-notes.js';
import { registerMergeTools } from '../../../src/tools/write/merge.js';
import { registerSystemTools } from '../../../src/tools/write/system.js';
import { registerPolicyTools } from '../../../src/tools/write/policy.js';
import { registerInitTools } from '../../../src/tools/write/enrich.js';

describe('T13: HTTP Transport', () => {
  describe('write tool getter pattern', () => {
    it('registerMutationTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      const getter = () => '/test/vault';
      registerMutationTools(server, getter);

      expect(toolNames).toContain('vault_add_to_section');
      expect(toolNames).toContain('vault_remove_from_section');
      expect(toolNames).toContain('vault_replace_in_section');
    });

    it('registerTaskTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerTaskTools(server, () => '/test/vault');

      // vault_toggle_task retired (T43 B3+) — merged into tasks(action: toggle)
      expect(toolNames).not.toContain('vault_toggle_task');
      expect(toolNames).toContain('vault_add_task');
    });

    it('registerFrontmatterTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerFrontmatterTools(server, () => '/test/vault');

      expect(toolNames).toContain('vault_update_frontmatter');
    });

    it('registerNoteTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerNoteTools(server, () => '/test/vault');

      expect(toolNames).toContain('vault_create_note');
      expect(toolNames).toContain('vault_delete_note');
    });

    it('registerMoveNoteTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerMoveNoteTools(server, () => '/test/vault');

      expect(toolNames).toContain('vault_move_note');
      expect(toolNames).toContain('vault_rename_note');
    });

    it('registerMergeTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerMergeTools(server, () => '/test/vault');

      expect(toolNames).toContain('merge_entities');
      expect(toolNames).toContain('absorb_as_alias');
    });

    it('registerSystemTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerSystemTools(server, () => '/test/vault');

      expect(toolNames).toContain('vault_undo_last_mutation');
    });

    it('registerPolicyTools accepts getVaultPath getter', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerPolicyTools(server, () => '/test/vault');

      expect(toolNames).toContain('policy');
    });

    it('registerInitTools is a no-op (vault_init retired T43)', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const toolNames: string[] = [];
      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        toolNames.push(name);
        return origTool(name, ...args);
      };

      registerInitTools(server, () => '/test/vault', () => null);

      // vault_init retired (T43) — registerInitTools is now a no-op
      expect(toolNames).not.toContain('vault_init');
      expect(toolNames).toHaveLength(0);
    });

    it('getter is called at invocation time, not registration time', () => {
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      let currentPath = '/vault/a';
      const getter = vi.fn(() => currentPath);

      registerFrontmatterTools(server, getter);

      // Getter should NOT have been called during registration
      expect(getter).not.toHaveBeenCalled();

      // Change the path — when handler runs, it should see the new value
      currentPath = '/vault/b';
      // We can't easily invoke the handler without a full MCP flow,
      // but we've verified the getter wasn't eagerly evaluated
    });

    it('all 9 write registration functions accept getVaultPath getter', () => {
      // This test verifies the type signatures compile correctly
      // by constructing all registration calls with a getter
      const server = new McpServer({ name: 'test', version: '0.0.0' });
      const getter = () => '/test/vault';
      const allToolNames: string[] = [];

      const origTool = server.tool.bind(server);
      (server as any).tool = (name: string, ...args: any[]) => {
        allToolNames.push(name);
        return origTool(name, ...args);
      };

      registerMutationTools(server, getter);
      registerTaskTools(server, getter);
      registerFrontmatterTools(server, getter);
      registerNoteTools(server, getter);
      registerMoveNoteTools(server, getter);
      registerMergeTools(server, getter);
      registerSystemTools(server, getter);
      registerPolicyTools(server, getter);
      registerInitTools(server, getter, () => null);

      // All 9 registration functions should register their tools
      // (vault_init retired T43, registerInitTools is now a no-op)
      // (vault_toggle_task retired T43 B3+, merged into tasks(action: toggle) → 13 tools)
      expect(allToolNames.length).toBeGreaterThanOrEqual(13);

      // Verify key tools are present
      const expectedTools = [
        'vault_add_to_section', 'vault_remove_from_section', 'vault_replace_in_section',
        // vault_toggle_task retired (T43 B3+) — merged into tasks(action: toggle)
        'vault_add_task',
        'vault_update_frontmatter',
        'vault_create_note', 'vault_delete_note',
        'vault_move_note', 'vault_rename_note',
        'merge_entities', 'absorb_as_alias',
        'vault_undo_last_mutation',
        'policy',
      ];
      for (const tool of expectedTools) {
        expect(allToolNames).toContain(tool);
      }
    });
  });
});
