import { RulerDataSourceConfig } from 'app/types/unified-alerting';

import { mockDataSource } from '../mocks';
import { setupDataSources } from '../testSetup/datasources';
import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource';

import { rulerUrlBuilder } from './ruler';

const grafanaConfig: RulerDataSourceConfig = {
  dataSourceName: GRAFANA_RULES_SOURCE_NAME,
  apiVersion: 'legacy',
};

const mimirConfig: RulerDataSourceConfig = {
  dataSourceName: 'Mimir-cloud',
  apiVersion: 'config',
};

beforeAll(() => {
  setupDataSources(
    mockDataSource({ type: DataSourceType.Prometheus, name: 'Mimir-cloud', uid: 'mimir-1' }),
    mockDataSource({ type: DataSourceType.Prometheus, name: 'Cortex', uid: 'cortex-1' })
  );
});

describe('rulerUrlBuilder', () => {
  it('Should use /api/v1/rules endpoint with subtype = cortex param for legacy api version', () => {
    // Arrange
    const config: RulerDataSourceConfig = {
      dataSourceName: 'Cortex',
      apiVersion: 'legacy',
    };

    // Act
    const builder = rulerUrlBuilder(config);

    const rules = builder.rules();
    const namespace = builder.namespace('test-ns');
    const group = builder.namespaceGroup('test-ns', 'test-gr');

    // Assert
    expect(rules.path).toBe('/api/ruler/cortex-1/api/v1/rules');
    expect(rules.params).toMatchObject({ subtype: 'cortex' });

    expect(namespace.path).toBe('/api/ruler/cortex-1/api/v1/rules/test-ns');
    expect(namespace.params).toMatchObject({ subtype: 'cortex' });

    expect(group.path).toBe('/api/ruler/cortex-1/api/v1/rules/test-ns/test-gr');
    expect(group.params).toMatchObject({ subtype: 'cortex' });
  });

  it('Should use /api/v1/rules endpoint with subtype = mimir parameter for config api version', () => {
    // Act
    const builder = rulerUrlBuilder(mimirConfig);

    const rules = builder.rules();
    const namespace = builder.namespace('test-ns');
    const group = builder.namespaceGroup('test-ns', 'test-gr');

    // Assert
    expect(rules.path).toBe('/api/ruler/mimir-1/api/v1/rules');
    expect(rules.params).toMatchObject({ subtype: 'mimir' });

    expect(namespace.path).toBe('/api/ruler/mimir-1/api/v1/rules/test-ns');
    expect(namespace.params).toMatchObject({ subtype: 'mimir' });

    expect(group.path).toBe('/api/ruler/mimir-1/api/v1/rules/test-ns/test-gr');
    expect(group.params).toMatchObject({ subtype: 'mimir' });
  });

  it('Should append subtype parameter when custom ruler enabled', () => {
    // Act
    const builder = rulerUrlBuilder(mimirConfig);

    const rules = builder.rules();
    const namespace = builder.namespace('test-ns');
    const group = builder.namespaceGroup('test-ns', 'test-gr');

    // Assert
    expect(rules.params).toMatchObject({ subtype: 'mimir' });
    expect(namespace.params).toMatchObject({ subtype: 'mimir' });
    expect(group.params).toMatchObject({ subtype: 'mimir' });
  });

  it('Should append dashboard_uid and panel_id for rules endpoint when specified', () => {
    // Act
    const builder = rulerUrlBuilder(mimirConfig);
    const rules = builder.rules({ dashboardUID: 'dashboard-uid', panelId: 1234 });

    // Assert
    expect(rules.params).toMatchObject({ dashboard_uid: 'dashboard-uid', panel_id: '1234', subtype: 'mimir' });
  });

  describe('When slash in namespace or group', () => {
    it('Should use QUERY_NAMESPACE and QUERY_GROUP path placeholders and include names in query string params', () => {
      // Act
      const builder = rulerUrlBuilder(mimirConfig);

      const namespace = builder.namespace('test/ns');
      const group = builder.namespaceGroup('test/ns', 'test/gr');

      // Assert
      expect(namespace.path).toBe('/api/ruler/mimir-1/api/v1/rules/QUERY_NAMESPACE');
      expect(namespace.params).toMatchObject({ subtype: 'mimir', namespace: 'test/ns' });

      expect(group.path).toBe('/api/ruler/mimir-1/api/v1/rules/QUERY_NAMESPACE/QUERY_GROUP');
      expect(group.params).toMatchObject({ subtype: 'mimir', namespace: 'test/ns', group: 'test/gr' });
    });

    it('Should use the tag replacement only when the slash is present', () => {
      // Act
      const builder = rulerUrlBuilder(mimirConfig);

      const group = builder.namespaceGroup('test-ns', 'test/gr');

      // Assert
      expect(group.path).toBe('/api/ruler/mimir-1/api/v1/rules/test-ns/QUERY_GROUP');
      expect(group.params).toMatchObject({ subtype: 'mimir', group: 'test/gr' });
    });

    // GMA uses folderUIDs as namespaces and they should never contain slashes
    it('Should only replace the group segment for Grafana-managed rules', () => {
      // Act
      const builder = rulerUrlBuilder(grafanaConfig);

      const group = builder.namespaceGroup('test/ns', 'test/gr');

      // Assert
      expect(group.path).toBe(`/api/ruler/grafana/api/v1/rules/${encodeURIComponent('test/ns')}/QUERY_GROUP`);
      expect(group.params).toHaveProperty('group');
      expect(group.params).not.toHaveProperty('namespace');
    });
  });
});
