import {
  getPlatformClientInfo,
  buildUserAgent,
  getPlatformUserAgent,
  getPlatformCapabilities,
  requiresCapabilityDetection,
  PLATFORM_DETECTION_PATTERNS,
  MCP_APPS_EXTENSION_KEY,
} from '../platform-client-info';
import type { TestPlatformType } from '../platform-types';

describe('getPlatformClientInfo', () => {
  const cases: Array<[TestPlatformType, string, string]> = [
    ['openai', 'ChatGPT', '1.0'],
    ['ext-apps', 'mcp-ext-apps', '1.0'],
    ['claude', 'claude-desktop', '1.0'],
    ['cursor', 'cursor', '1.0'],
    ['continue', 'continue', '1.0'],
    ['cody', 'cody', '1.0'],
    ['gemini', 'gemini', '1.0'],
    ['generic-mcp', 'generic-mcp-client', '1.0'],
    ['unknown', 'mcp-test-client', '1.0'],
  ];

  it.each(cases)('should return { name: "%s", version: "%s" } for platform "%s"', (platform, name, version) => {
    const info = getPlatformClientInfo(platform);
    expect(info).toEqual({ name, version });
  });

  it('should return default info for an unrecognized platform value', () => {
    // Cast a truly unrecognized value to exercise the default switch branch.
    // 'unknown' is a valid TestPlatformType, so we need a value outside the union.
    const info = getPlatformClientInfo('not-a-real-platform' as TestPlatformType);
    expect(info).toEqual({ name: 'mcp-test-client', version: '1.0' });
  });
});

describe('buildUserAgent', () => {
  it('should concatenate name and version with a slash', () => {
    expect(buildUserAgent({ name: 'ChatGPT', version: '1.0' })).toBe('ChatGPT/1.0');
  });

  it('should work with arbitrary name/version', () => {
    expect(buildUserAgent({ name: 'my-client', version: '2.5.1' })).toBe('my-client/2.5.1');
  });
});

describe('getPlatformUserAgent', () => {
  it('should return the full user-agent string for a given platform', () => {
    expect(getPlatformUserAgent('openai')).toBe('ChatGPT/1.0');
    expect(getPlatformUserAgent('claude')).toBe('claude-desktop/1.0');
    expect(getPlatformUserAgent('cursor')).toBe('cursor/1.0');
    expect(getPlatformUserAgent('ext-apps')).toBe('mcp-ext-apps/1.0');
    expect(getPlatformUserAgent('unknown')).toBe('mcp-test-client/1.0');
  });
});

describe('PLATFORM_DETECTION_PATTERNS', () => {
  it('should match the user-agent generated by getPlatformUserAgent for each platform', () => {
    const platforms: TestPlatformType[] = [
      'openai',
      'ext-apps',
      'claude',
      'cursor',
      'continue',
      'cody',
      'gemini',
      'generic-mcp',
    ];

    for (const platform of platforms) {
      const ua = getPlatformUserAgent(platform);
      const pattern = PLATFORM_DETECTION_PATTERNS[platform];
      expect(pattern.test(ua)).toBe(true);
    }
  });

  it('unknown pattern should match any string', () => {
    expect(PLATFORM_DETECTION_PATTERNS['unknown'].test('anything-at-all')).toBe(true);
    expect(PLATFORM_DETECTION_PATTERNS['unknown'].test('')).toBe(true);
  });

  it('openai pattern should be case-insensitive', () => {
    expect(PLATFORM_DETECTION_PATTERNS['openai'].test('chatgpt')).toBe(true);
    expect(PLATFORM_DETECTION_PATTERNS['openai'].test('CHATGPT')).toBe(true);
    expect(PLATFORM_DETECTION_PATTERNS['openai'].test('ChatGPT/1.0')).toBe(true);
  });

  it('claude pattern should match both "claude" and "claude-desktop"', () => {
    expect(PLATFORM_DETECTION_PATTERNS['claude'].test('claude')).toBe(true);
    expect(PLATFORM_DETECTION_PATTERNS['claude'].test('claude-desktop')).toBe(true);
  });
});

describe('MCP_APPS_EXTENSION_KEY', () => {
  it('should be the expected string constant', () => {
    expect(MCP_APPS_EXTENSION_KEY).toBe('io.modelcontextprotocol/ui');
  });
});

describe('getPlatformCapabilities', () => {
  it('should return base capabilities with sampling and elicitation.form for non-ext-apps platforms', () => {
    const platforms: TestPlatformType[] = ['openai', 'claude', 'cursor', 'continue', 'cody', 'gemini', 'unknown'];
    for (const platform of platforms) {
      const caps = getPlatformCapabilities(platform);
      expect(caps.sampling).toEqual({});
      expect(caps.elicitation).toEqual({ form: {} });
      expect(caps.experimental).toBeUndefined();
    }
  });

  it('should include experimental io.modelcontextprotocol/ui extension for ext-apps', () => {
    const caps = getPlatformCapabilities('ext-apps');
    expect(caps.sampling).toEqual({});
    expect(caps.elicitation).toEqual({ form: {} });
    expect(caps.experimental).toBeDefined();
    if (!caps.experimental) return;
    expect(caps.experimental[MCP_APPS_EXTENSION_KEY]).toEqual({
      mimeTypes: ['text/html;profile=mcp-app'],
    });
  });
});

describe('requiresCapabilityDetection', () => {
  it('should return true only for ext-apps', () => {
    expect(requiresCapabilityDetection('ext-apps')).toBe(true);
  });

  it('should return false for all other platforms', () => {
    const others: TestPlatformType[] = [
      'openai',
      'claude',
      'cursor',
      'continue',
      'cody',
      'gemini',
      'generic-mcp',
      'unknown',
    ];
    for (const platform of others) {
      expect(requiresCapabilityDetection(platform)).toBe(false);
    }
  });
});
