/**
 * E2E Tests for Hook System
 *
 * Tests Will/Did hook patterns:
 * - Will hooks execute before tool
 * - Did hooks execute after tool
 * - Hook priority ordering
 */
import { test, expect } from '@frontmcp/testing';

test.describe('Hooks E2E', () => {
  test.use({
    server: 'apps/e2e/demo-e2e-hooks/src/main.ts',
    project: 'demo-e2e-hooks',
    publicMode: true,
  });

  test.describe('Hook Execution', () => {
    test('should execute will hooks before tool execution', async ({ mcp }) => {
      // Clear audit log first
      await mcp.tools.call('clear-audit-log', {});

      // Call the audited tool
      await mcp.tools.call('audited-tool', { message: 'test message' });

      // Get the audit log
      const result = await mcp.tools.call('get-audit-log', { toolName: 'audited-tool' });

      expect(result).toBeSuccessful();

      const content = JSON.stringify(result);
      // Should have will entries
      expect(content).toContain('"hookType":"will"');
    });

    test('should execute did hooks after tool execution', async ({ mcp }) => {
      await mcp.tools.call('clear-audit-log', {});
      await mcp.tools.call('audited-tool', { message: 'test message' });

      const result = await mcp.tools.call('get-audit-log', { toolName: 'audited-tool' });

      expect(result).toBeSuccessful();

      const content = JSON.stringify(result);
      // Should have did entries
      expect(content).toContain('"hookType":"did"');
    });

    test('should execute hooks in priority order', async ({ mcp }) => {
      await mcp.tools.call('clear-audit-log', {});
      await mcp.tools.call('audited-tool', { message: 'test' });

      const result = await mcp.tools.call('get-audit-log', {});

      expect(result).toBeSuccessful();

      const content = JSON.stringify(result);

      // Check execution order array contains expected patterns
      // Will hooks: high priority (100) runs before low priority (50)
      // Did hooks: high priority (100) runs before low priority (50)
      expect(content).toContain('will:execute:100');
      expect(content).toContain('will:execute:50');
      expect(content).toContain('did:execute:100');
      expect(content).toContain('did:execute:50');
    });

    test('should track execution order correctly', async ({ mcp }) => {
      await mcp.tools.call('clear-audit-log', {});
      await mcp.tools.call('audited-tool', { message: 'first' });
      await mcp.tools.call('audited-tool', { message: 'second' });

      // Get audit log filtered by tool name to get accurate count
      const result = await mcp.tools.call('get-audit-log', { toolName: 'audited-tool' });

      expect(result).toBeSuccessful();

      // Parse the data to verify entries count
      const data = result.json<{ entries: Array<{ hookType: string }> }>();
      expect(data).toBeDefined();
      expect(data.entries).toBeDefined();

      // Should have 8 entries for audited-tool
      // 2 audited-tool calls x 4 hooks each = 8 filtered entries
      expect(data.entries).toHaveLength(8);

      // Check will/did distribution
      const willEntries = data.entries.filter((e) => e.hookType === 'will');
      const didEntries = data.entries.filter((e) => e.hookType === 'did');
      expect(willEntries).toHaveLength(4);
      expect(didEntries).toHaveLength(4);
    });

    test('should capture duration in did hooks', async ({ mcp }) => {
      await mcp.tools.call('clear-audit-log', {});
      await mcp.tools.call('audited-tool', {
        message: 'delayed',
        delay: 50, // Small delay to ensure measurable duration
      });

      const result = await mcp.tools.call('get-audit-log', { toolName: 'audited-tool' });

      expect(result).toBeSuccessful();

      const content = JSON.stringify(result);
      // Should have durationMs field in did hooks
      expect(content).toContain('durationMs');
    });
  });

  test.describe('Resource Access', () => {
    test('should list audit log resource', async ({ mcp }) => {
      const resources = await mcp.resources.list();
      expect(resources).toContainResource('audit://log');
    });

    test('should read audit log from resource', async ({ mcp }) => {
      // Generate some audit entries
      await mcp.tools.call('audited-tool', { message: 'resource test' });

      const content = await mcp.resources.read('audit://log');

      expect(content).toBeSuccessful();
      expect(content).toHaveTextContent('entries');
      expect(content).toHaveTextContent('stats');
    });
  });

  test.describe('Prompt Access', () => {
    test('should list audit-summary prompt', async ({ mcp }) => {
      const prompts = await mcp.prompts.list();
      expect(prompts).toContainPrompt('audit-summary');
    });

    test('should generate audit summary', async ({ mcp }) => {
      // Generate some audit entries
      await mcp.tools.call('audited-tool', { message: 'summary test' });

      const result = await mcp.prompts.get('audit-summary', {});

      expect(result).toBeSuccessful();
      expect(result.messages.length).toBeGreaterThan(0);

      const message = result.messages[0];
      if (message.content.type === 'text') {
        expect(message.content.text).toContain('Audit Log Summary');
        expect(message.content.text).toContain('Hook Execution Order');
      }
    });
  });

  test.describe('Tool Discovery', () => {
    test('should list all hook demo tools', async ({ mcp }) => {
      const tools = await mcp.tools.list();

      expect(tools).toContainTool('audited-tool');
      expect(tools).toContainTool('get-audit-log');
      expect(tools).toContainTool('clear-audit-log');
    });
  });
});
