import { describe, test, expect } from 'vitest';

import { IntegrationAuthType } from './auth.js';
import {
  DatasourceConfiguration,
  isAuthenticatedDatasourceConfig,
  isAuthenticatedDatasourceConfigWithDynamicAuthType,
  getAuthTypeFromConfig
} from './index.js';

describe('isAuthenticatedDatasourceConfig', () => {
  test('returns true for config with authConfig and authType', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authType: IntegrationAuthType.OAUTH2_CODE
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(true);
  });

  test('returns false for config with authConfig and authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: 'fields' // This field must exist for the test to pass
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config without authConfig', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authType: IntegrationAuthType.OAUTH2_CODE
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authConfig but no authType or authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      }
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authType but no authConfig', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authType: IntegrationAuthType.OAUTH2_CODE
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authTypeField but no authConfig', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authTypeField: 'connectionType'
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for empty config', () => {
    const config: DatasourceConfiguration = {
      name: 'test'
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns true for config with authConfig and both authType and authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authType: IntegrationAuthType.OAUTH2_CODE,
      authTypeField: 'connectionType',
      connectionType: 'fields' // This field must exist for the test to pass
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(true);
  });

  test('returns false for config with authConfig but empty authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: ''
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authConfig but undefined authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: undefined
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authConfig but authTypeField pointing to non-existent field', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'nonExistentField'
      // nonExistentField is not defined in the config
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authConfig but undefined authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: undefined
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authConfig and authTypeField pointing to undefined field', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType'
      // connectionType is not defined, so it's undefined
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });

  test('returns false for config with authConfig and authTypeField pointing to undefined field', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: undefined
    };

    expect(isAuthenticatedDatasourceConfig(config)).toBe(false);
  });
});

describe('isAuthenticatedDatasourceConfigWithDynamicAuthType', () => {
  test('returns true for config with authConfig and valid authTypeField', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: 'oauth2'
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });

  test('returns true for config with authConfig and authTypeField pointing to non-empty string', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'authMethod',
      authMethod: 'api_key'
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });

  test('returns false for config without authConfig', () => {
    const config = {
      name: 'test',
      authTypeField: 'connectionType',
      connectionType: 'oauth2'
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns false for config with authConfig but no authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      }
    };

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns false for config with authConfig and empty authTypeField', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: '',
      connectionType: 'oauth2'
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns false for config with authConfig and undefined authTypeField', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: undefined,
      connectionType: 'oauth2'
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns false for config with authConfig and authTypeField pointing to undefined field', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType'
      // connectionType is not defined
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns false for config with authConfig and authTypeField pointing to null field', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: null
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns false for config with authConfig and authTypeField pointing to empty string', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: ''
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns true for config with authConfig and authTypeField pointing to zero', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: 0
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });

  test('returns true for config with authConfig and authTypeField pointing to false', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: false
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });

  test('returns true for config with authConfig and authTypeField pointing to object', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: { type: 'oauth2' }
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });

  test('returns true for config with authConfig and authTypeField pointing to array', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: ['oauth2', 'api_key']
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });

  test('returns false for empty config', () => {
    const config: DatasourceConfiguration = {
      name: 'test'
    };

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns false for config with authConfig but authTypeField pointing to non-existent field', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'nonExistentField'
      // nonExistentField is not defined in the config
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(false);
  });

  test('returns true for config with authConfig and authTypeField pointing to numeric value', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: 42
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });

  test('returns true for config with authConfig and authTypeField pointing to boolean true', () => {
    const config = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: true
    } as DatasourceConfiguration;

    expect(isAuthenticatedDatasourceConfigWithDynamicAuthType(config)).toBe(true);
  });
});

describe('getAuthTypeFromConfig', () => {
  test('returns authType for config with direct authType field', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authType: IntegrationAuthType.OAUTH2_CODE
    };

    expect(getAuthTypeFromConfig(config)).toBe(IntegrationAuthType.OAUTH2_CODE);
  });

  test('returns authType for config with authTypeField pointing to valid field', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: 'fields'
    };

    expect(getAuthTypeFromConfig(config)).toBe('fields');
  });

  test('returns undefined for non-authenticated config', () => {
    const config: DatasourceConfiguration = {
      name: 'test'
    };

    expect(getAuthTypeFromConfig(config)).toBe(undefined);
  });

  test('returns undefined for config with authConfig but no authType or authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      }
    };

    expect(getAuthTypeFromConfig(config)).toBe(undefined);
  });

  test('returns undefined for config with authTypeField pointing to undefined field', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType'
      // connectionType is not defined
    };

    expect(getAuthTypeFromConfig(config)).toBe(undefined);
  });

  test('returns undefined for config with authTypeField pointing to undefined field', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authTypeField: 'connectionType',
      connectionType: undefined
    };

    expect(getAuthTypeFromConfig(config)).toBe(undefined);
  });

  test('prioritizes direct authType over authTypeField', () => {
    const config: DatasourceConfiguration = {
      name: 'test',
      authConfig: {
        clientId: 'test-client',
        clientSecret: 'test-secret'
      },
      authType: IntegrationAuthType.OAUTH2_CODE,
      authTypeField: 'connectionType',
      connectionType: 'fields'
    };

    expect(getAuthTypeFromConfig(config)).toBe(IntegrationAuthType.OAUTH2_CODE);
  });
});
