import * as Models from '../models/models';
import * as lodash from 'lodash';
import * as mongoose from 'mongoose';

export default class MongoDbInserts {
  private mongooseModels: Models.MongooseModels;

  public constructor( mongooseModels: Models.MongooseModels ) {
    this.mongooseModels = mongooseModels;
  }

  public async insertReport( report: Models.ExtendedReport ): Promise<mongoose.Types.ObjectId> {
    const mongoReport: Models.ExtendedReport = lodash.cloneDeep( report );
    const features = lodash.cloneDeep( report?.features );
    mongoReport.features = [];
    // mongoReport._id = '';
    const element = await this.mongooseModels.reportModel.create( mongoReport );
    // element.features = element.id as mongoose.Types.ObjectId[];
    await element.save();
    // const reportId = mongoReport._id as mongoose.Types.ObjectId;

    // if ( features?.length > 0 ) {
    // mongoReport.featuresId = new ObjectId();
    // features = features.sort( ( a, b ) => ( a.id > b.id ) ? 1 : -1 );
    await Promise.all(
      features.map( async ( feature ) => {
        // feature.Index = index;
        const scenarios: Models.Scenario[] | null | undefined = lodash.cloneDeep( feature.elements );
        feature.reportId = element._id as mongoose.Types.ObjectId;
        delete feature.elements;
        const featureInDb = await this.mongooseModels.featureModel.create( feature );
        // if( scenarios != null ) {
        await this._insertScenarios( scenarios as Models.Scenario[], featureInDb._id );
        // }

        return feature;
      } ),
    );
    // }

    return element._id as mongoose.Types.ObjectId;
  }

  /**
   * Insert the scenarios of a feature into the mongodb database
   *
   * @param {*} feature
   * @param {*} reportFeaturesId
   * @param {*} index
   */
  private async _insertScenarios( scenarios: Models.Scenario[], reportFeaturesId: mongoose.Types.ObjectId ): Promise<void> {
    // feature.reportId = reportFeaturesId;
    // feature.scenariosId = new ObjectId();
    // feature.index = index;
    if ( typeof scenarios !== 'undefined' && scenarios?.length > 0 ) {
      await Promise.all(
        scenarios.map( async ( scenario ) => {
          scenario.featureId = reportFeaturesId;
          // scenario.Index = featuresIndex;
          const scenarioSteps = lodash.cloneDeep( scenario.steps );
          delete scenario.steps;
          const scenarioDb = await this.mongooseModels.scenarioModel.create( scenario );
          await this._insertScenarioSteps( scenarioSteps, scenarioDb._id );
          return scenario;
        } )
      );
    }
  }

  /**
   * Insert the steps of a scenario into a mongodb database
   *
   * @param {*} scenarioSteps
   * @param {*} scenarioStepsId
   * @param {*} reportFeaturesId
   */
  private async _insertScenarioSteps( scenarioSteps: Models.Step[] | null | undefined, scenarioStepsId: mongoose.Types.ObjectId ): Promise<void> {
    if ( typeof scenarioSteps !== 'undefined' && scenarioSteps !== null && scenarioSteps.length > 0 ) {
      await Promise.all(
        scenarioSteps.map( async ( step ) => {
          step.scenarioId = scenarioStepsId;
          // step.Index = index;
          // delete step.attachments;
          await this.mongooseModels.stepModel.create( step );
          // delete step.scenarioId;
          // delete step.index;
          return step;
        } )
      );
    }
  }
}
