// Import Mango
import { closeMango, Collection } from '../../src';

// Import types
import Id from '../types/Id';
import Lock from '../types/Lock';
import TestDocument from '../types/TestDocument';

// Import constants
import COLLECTION_OPTS from '../constants/COLLECTION_OPTS';
import TEST_DOCUMENT from '../constants/TEST_DOCUMENT';
import SECOND_TEST_DOCUMENT from '../constants/SECOND_TEST_DOCUMENT';

// Import helpers
import getLockCollectionName from './getLockCollectionName';
import getLockCollectionOpts from './getLockCollectionOpts';

/*------------------------------------------------------------------------*/
/*                           Helper Functions                             */
/*------------------------------------------------------------------------*/

/**
 * Clean up all instances of a test document from a collection.
 * @author Benedikt Arnarsson
 * @param collection the collection to clean-up, should contain test documents
 * @param testDocument the test document that is being cleaned
 */
const cleanupOneCollection = async <T extends { id: Id }>(
  collection: Collection<T>,
  testDocument: TestDocument,
) => {
  const { id } = testDocument;

  const docs = await collection.find({ id });
  await Promise.all(docs.map(async (doc) => {
    return collection.delete({ id: doc.id });
  }));
};

/*------------------------------------------------------------------------*/
/*                             Main Function                              */
/*------------------------------------------------------------------------*/

/**
 * Function for cleaning up the test collection in the DB.
 * @author Benedikt Arnarsson
 */
const cleanupTestCollections = async () => {
  // TODO: if we make multiple test documents, make sure to iterate

  // eslint-disable-next-line no-restricted-syntax
  for (const [collectionName, options] of Object.entries(COLLECTION_OPTS)) {
    const cleanupCollection = new Collection<TestDocument>(collectionName, options);
    if (cleanupCollection.getSupportConcurrency()) {
      const lockCollection = new Collection<Lock>(getLockCollectionName(collectionName), getLockCollectionOpts());
      await cleanupOneCollection(lockCollection, TEST_DOCUMENT);
      await cleanupOneCollection(lockCollection, SECOND_TEST_DOCUMENT);
    }

    await cleanupOneCollection(cleanupCollection, TEST_DOCUMENT);
    await cleanupOneCollection(cleanupCollection, SECOND_TEST_DOCUMENT);
  }
};

export default cleanupTestCollections;

/*------------------------------------------------------------------------*/
/*                                 Main                                   */
/*------------------------------------------------------------------------*/

if (require.main === module) {
  // Call this with (ts)-node to cleanup
  (async () => {
    await cleanupTestCollections();
    await closeMango();
  })();
}
