import { convertParametersToTypes } from '../../src/utils/parameterConversion.js';

// Integration tests for OpenAPI controller's parameter type conversion
describe('OpenAPI Controller - Parameter Type Conversion Integration', () => {
  test('should convert integer parameters correctly', () => {
    const queryParams = {
      limit: '5',
      offset: '10',
      name: 'test'
    };
    
    const inputSchema = {
      type: 'object',
      properties: {
        limit: { type: 'integer' },
        offset: { type: 'integer' },
        name: { type: 'string' }
      }
    };

    const result = convertParametersToTypes(queryParams, inputSchema);

    expect(result).toEqual({
      limit: 5,       // Converted to integer
      offset: 10,     // Converted to integer
      name: 'test'    // Remains string
    });
  });

  test('should convert number parameters correctly', () => {
    const queryParams = {
      price: '19.99',
      discount: '0.15'
    };
    
    const inputSchema = {
      type: 'object',
      properties: {
        price: { type: 'number' },
        discount: { type: 'number' }
      }
    };

    const result = convertParametersToTypes(queryParams, inputSchema);

    expect(result).toEqual({
      price: 19.99,
      discount: 0.15
    });
  });

  test('should convert boolean parameters correctly', () => {
    const queryParams = {
      enabled: 'true',
      disabled: 'false',
      active: '1',
      inactive: '0'
    };
    
    const inputSchema = {
      type: 'object',
      properties: {
        enabled: { type: 'boolean' },
        disabled: { type: 'boolean' },
        active: { type: 'boolean' },
        inactive: { type: 'boolean' }
      }
    };

    const result = convertParametersToTypes(queryParams, inputSchema);

    expect(result).toEqual({
      enabled: true,
      disabled: false,
      active: true,
      inactive: false
    });
  });

  test('should convert array parameters correctly', () => {
    const queryParams = {
      tags: 'tag1,tag2,tag3',
      ids: '1,2,3'
    };
    
    const inputSchema = {
      type: 'object',
      properties: {
        tags: { type: 'array' },
        ids: { type: 'array' }
      }
    };

    const result = convertParametersToTypes(queryParams, inputSchema);

    expect(result).toEqual({
      tags: ['tag1', 'tag2', 'tag3'],
      ids: ['1', '2', '3']
    });
  });

  test('should handle missing schema gracefully', () => {
    const queryParams = {
      limit: '5',
      name: 'test'
    };

    const result = convertParametersToTypes(queryParams, {});

    expect(result).toEqual({
      limit: '5',     // Should remain as string
      name: 'test'    // Should remain as string
    });
  });

  test('should handle properties not in schema', () => {
    const queryParams = {
      limit: '5',
      unknownParam: 'value'
    };
    
    const inputSchema = {
      type: 'object',
      properties: {
        limit: { type: 'integer' }
      }
    };

    const result = convertParametersToTypes(queryParams, inputSchema);

    expect(result).toEqual({
      limit: 5,                     // Converted based on schema
      unknownParam: 'value'         // Kept as is (no schema)
    });
  });

  test('should handle invalid number conversion gracefully', () => {
    const queryParams = {
      limit: 'not-a-number',
      price: 'invalid'
    };
    
    const inputSchema = {
      type: 'object',
      properties: {
        limit: { type: 'integer' },
        price: { type: 'number' }
      }
    };

    const result = convertParametersToTypes(queryParams, inputSchema);

    expect(result).toEqual({
      limit: 'not-a-number',  // Should remain as string when conversion fails
      price: 'invalid'        // Should remain as string when conversion fails
    });
  });
});

// Test the new OpenAPI endpoints functionality
describe('OpenAPI Granular Endpoints', () => {
  // Mock the required services
  const mockGetAvailableServers = jest.fn();
  const mockGenerateOpenAPISpec = jest.fn();
  const mockGetGroupByIdOrName = jest.fn();

  beforeEach(() => {
    jest.clearAllMocks();
  });

  test('should generate server-specific OpenAPI spec', async () => {
    // Mock available servers
    mockGetAvailableServers.mockResolvedValue(['server1', 'server2']);
    
    // Mock OpenAPI spec generation
    const mockSpec = { openapi: '3.0.3', info: { title: 'server1 MCP API' } };
    mockGenerateOpenAPISpec.mockResolvedValue(mockSpec);

    // Test server spec generation options
    const expectedOptions = {
      title: 'server1 MCP API',
      description: 'OpenAPI specification for server1 MCP server tools',
      serverFilter: ['server1']
    };

    // Verify that the correct options would be passed
    expect(expectedOptions.serverFilter).toEqual(['server1']);
    expect(expectedOptions.title).toBe('server1 MCP API');
  });

  test('should generate group-specific OpenAPI spec', async () => {
    // Mock group data
    const mockGroup = {
      id: 'group1',
      name: 'webtools',
      servers: [
        { name: 'server1', tools: 'all' },
        { name: 'server2', tools: ['tool1', 'tool2'] }
      ]
    };
    mockGetGroupByIdOrName.mockReturnValue(mockGroup);

    // Mock OpenAPI spec generation
    const mockSpec = { openapi: '3.0.3', info: { title: 'webtools Group MCP API' } };
    mockGenerateOpenAPISpec.mockResolvedValue(mockSpec);

    // Test group spec generation options
    const expectedOptions = {
      title: 'webtools Group MCP API',
      description: 'OpenAPI specification for webtools group tools',
      groupFilter: 'webtools'
    };

    // Verify that the correct options would be passed
    expect(expectedOptions.groupFilter).toBe('webtools');
    expect(expectedOptions.title).toBe('webtools Group MCP API');
  });

  test('should handle non-existent server', async () => {
    // Mock available servers (not including 'nonexistent')
    mockGetAvailableServers.mockResolvedValue(['server1', 'server2']);

    // Verify error handling for non-existent server
    const serverExists = ['server1', 'server2'].includes('nonexistent');
    expect(serverExists).toBe(false);
  });

  test('should handle non-existent group', async () => {
    // Mock group lookup returning null
    mockGetGroupByIdOrName.mockReturnValue(null);

    // Verify error handling for non-existent group
    const group = mockGetGroupByIdOrName('nonexistent');
    expect(group).toBeNull();
  });

  test('should decode URL-encoded server and tool names with slashes', () => {
    // Test that URL-encoded names with slashes are properly decoded
    const encodedServerName = 'com.atlassian%2Fatlassian-mcp-server';
    const encodedToolName = 'atlassianUserInfo';

    const decodedServerName = decodeURIComponent(encodedServerName);
    const decodedToolName = decodeURIComponent(encodedToolName);

    expect(decodedServerName).toBe('com.atlassian/atlassian-mcp-server');
    expect(decodedToolName).toBe('atlassianUserInfo');
  });
});