// Import MongoDB
import MongoDB from 'mongodb';

// Import dbState
import dbState from '../dbState';

// Import types
import CollectionOpts from '../types/CollectionOpts';

/**
 * Initialize a collection.
 * @author Gabe Abrams
 * @param collectionName the name of the collection
 * @param options the options tied to the collection
 * @returns a Promise which resolves to the Mongo collection
 */
const initCollection = async (
  collectionName: string,
  options: CollectionOpts,
): Promise<MongoDB.Collection<MongoDB.Document>> => {
  // Get the collection names
  const collectionNames = await dbState.initDB;

  // Variable for the collection
  let collection: MongoDB.Collection<MongoDB.Document>;

  // Create collection if it doesn't exist
  if (collectionNames.indexOf(collectionName) < 0) {
    // Collection doesn't exist. Create it
    try {
      // Create collection
      await dbState.db.createCollection(collectionName);

      // Get the collection
      collection = dbState.db.collection(collectionName);
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log('DCE-MANGO: An error occurred while creating collections. Fatal error. Now exiting.');
      // eslint-disable-next-line no-console
      console.log(err);
      process.exit(1);
    }
  } else {
    // Collection exists. Get it
    collection = dbState.db.collection(collectionName);
  }

  // Get the indexes
  const existingIndexes = await collection.indexes();

  // If any of the indexes are old, drop them all
  const dropAllIndexes = (
    existingIndexes
      .some((index: { name?: string }) => {
        // Ignore invalid indexes
        if (!index || !index.name || typeof index.name !== 'string') {
          return false;
        }

        // Ignore ttl index
        if (index.name === 'ttl-index') {
          return false;
        }

        // Ignore default index
        if (index.name.startsWith('_')) {
          return false;
        }

        // Check if this index is from a previous version
        return (!index.name.includes(dbState.schemaVersionTag));
      })
  );

  // Drop all indexes if need be
  if (dropAllIndexes) {
    try {
      // eslint-disable-next-line no-console
      console.log(`DCE-MANGO: Found old schema for collection ${collectionName}! Dropping all indexes and re-creating them.`);
      await collection.dropIndexes();
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log('DCE-MANGO: An error occurred while dropping old indexes. Fatal error. Now exiting.');
      // eslint-disable-next-line no-console
      console.log(err);
      process.exit(1);
    }
  }

  // Gather a list of indexes that need to be created
  const indexesToCreate = [];

  // Add unique index to the list
  if (options.uniqueIndexKey) {
    // Create index options
    const indexOpts = {
      key: {
        [options.uniqueIndexKey]: 1,
      },
      name: `main-${options.uniqueIndexKey}-unique-index-${dbState.schemaVersionTag}`,
      unique: true,
      background: false,
    } as any;

    // Add expiry
    if (options.expireAfterSeconds) {
      indexOpts.expireAfterSeconds = options.expireAfterSeconds;
    }

    // Add the index to the list
    indexesToCreate.push(indexOpts);
  }

  // Add TTL for DocDB
  if (options.expireAfterSeconds) {
    indexesToCreate.push({
      key: {
        lastUpdatedForTTL: 1,
      },
      name: `ttl-index-${dbState.schemaVersionTag}`,
      expireAfterSeconds: options.expireAfterSeconds,
      background: false,
      unique: false,
    });
  }

  // Add secondary indexes to the list
  (options.indexKeys || []).forEach((secondaryIndexKey: any) => {
    indexesToCreate.push({
      key: {
        [secondaryIndexKey]: 1,
      },
      name: `secondary-${secondaryIndexKey}-index-${dbState.schemaVersionTag}`,
      unique: false,
      background: false,
    });
  });

  // Create the indexes
  try {
    await collection.createIndexes(indexesToCreate);
    if ((process.env.MANGO_LOG_LEVEL ?? '').toLowerCase() === 'info') {
      // eslint-disable-next-line no-console
      console.log('DCE-MANGO: Created indexes. ', indexesToCreate);
    }
  } catch (err) {
    // eslint-disable-next-line no-console
    console.log('DCE-MANGO: An error occurred while creating indexes. Fatal error. Now exiting.');
    // eslint-disable-next-line no-console
    console.log(err);
    process.exit(1);
  }

  // Return the collection
  return collection;
};

export default initCollection;
