/*
 * Copyright (C) 2022 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {TestBed} from '@angular/core/testing';
import {SCFacet, SCThing, SCFacetBucket} from '@openstapps/core';
import {sampleAggregations} from '../../_helpers/data/sample-configuration';
import {sampleThingsMap} from '../../_helpers/data/sample-things';
import {DataFacetsProvider} from './data-facets.provider';
import {DataModule} from './data.module';
import {DataProvider} from './data.provider';
import {StAppsWebHttpClient} from './stapps-web-http-client.provider';

describe('DataProvider', () => {
  let dataFacetsProvider: DataFacetsProvider;
  const sampleFacets: SCFacet[] = [
    {
      buckets: [
        {key: 'education', count: 4},
        {key: 'learn', count: 3},
        {key: 'computer', count: 3},
      ],
      field: 'categories',
    },
    {
      buckets: [
        {key: 'Major One', count: 1},
        {key: 'Major Two', count: 2},
        {key: 'Major Three', count: 1},
      ],
      field: 'majors',
    },
    {
      buckets: [
        {key: 'building', count: 3},
        {key: 'room', count: 7},
      ],
      field: 'type',
    },
  ];

  const sampleFacetsMap: {[key: string]: {[key: string]: number}} = {
    categories: {education: 4, learn: 3, computer: 3},
    majors: {'Major One': 1, 'Major Two': 2, 'Major Three': 1},
    type: {building: 3, room: 7},
  };

  const sampleItems: SCThing[] = [
    ...sampleThingsMap.building,
    ...sampleThingsMap.person,
    ...sampleThingsMap.room,
    ...sampleThingsMap['academic event'],
  ];

  const sampleBuckets: SCFacetBucket[] = [
    {key: 'foo', count: 1},
    {key: 'bar', count: 2},
    {key: 'foo bar', count: 3},
  ];
  const sampleBucketsMap: {[key: string]: number} = {
    'foo': 1,
    'bar': 2,
    'foo bar': 3,
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [DataModule],
      providers: [DataProvider, StAppsWebHttpClient],
    });
    dataFacetsProvider = TestBed.inject(DataFacetsProvider);
  });

  it('should add buckets properly', () => {
    let bucketsMap: {[key: string]: number} = {};
    bucketsMap = dataFacetsProvider.addBuckets(bucketsMap, ['foo']);
    expect(bucketsMap).toEqual({foo: 1});

    bucketsMap = dataFacetsProvider.addBuckets(bucketsMap, ['foo']);
    expect(bucketsMap).toEqual({foo: 2});

    bucketsMap = dataFacetsProvider.addBuckets(bucketsMap, ['bar']);
    expect(bucketsMap).toEqual({foo: 2, bar: 1});
  });

  it('should convert buckets to buckets map', () => {
    expect(dataFacetsProvider.bucketsToMap(sampleBuckets)).toEqual(sampleBucketsMap);
  });

  it('should convert buckets map into buckets', () => {
    expect(dataFacetsProvider.mapToBuckets(sampleBucketsMap)).toEqual(sampleBuckets);
  });

  it('should convert facets into a facets map', () => {
    expect(dataFacetsProvider.facetsToMap(sampleFacets)).toEqual(sampleFacetsMap);
  });

  it('should convert facets map into facets', () => {
    expect(dataFacetsProvider.mapToFacets(sampleFacetsMap)).toEqual(sampleFacets);
  });

  it('should extract facets (and append them if needed) from the data', () => {
    const sampleCombinedFacets: SCFacet[] = [
      {
        buckets: [
          {key: 'computer', count: 3},
          {key: 'course', count: 1},
          {key: 'education', count: 5},
          {key: 'learn', count: 3},
          {key: 'library', count: 1},
          {key: 'practicum', count: 1},
        ],
        field: 'categories',
      },
      {
        buckets: [
          {key: 'Major One', count: 2},
          {key: 'Major Two', count: 4},
          {key: 'Major Three', count: 2},
        ],
        field: 'majors',
      },
      {
        buckets: [
          {key: 'building', count: 4},
          {key: 'academic event', count: 2},
          {key: 'person', count: 2},
          {key: 'room', count: 8},
        ],
        field: 'type',
      },
    ];
    const checkEqual = (expected: SCFacet[], actual: SCFacet[]) => {
      const expectedMap = dataFacetsProvider.facetsToMap(expected);
      const actualMap = dataFacetsProvider.facetsToMap(actual);
      for (const key of Object.keys(actualMap)) {
        for (const subKey of Object.keys(actualMap[key])) {
          expect(actualMap[key][subKey]).toBe(expectedMap[key][subKey]);
        }
      }
    };
    checkEqual(
      dataFacetsProvider.extractFacets(sampleItems, sampleAggregations, sampleFacets),
      sampleCombinedFacets,
    );
  });
});
