'use strict';

// GLOBAL
const path = require('path');

// UTILS
const utils = require('../../../utils');

// CSDR RELATED
const initUtils = require('../../init/init-utils');
const installUtils = require('../../install/install-utils');
const metadataUtils = require('../../metadata/metadata-utils');
const versionUtils = require('../../version/version-utils');
const configUtils = require('../../config/config-utils');

// LOCAL TEST :
// - symlink eUI tools sources to node_modules of standalone pkg folder node_modules to test
// - execute this command on the standalone pkg folder :
// npx @eui/tools release-app-standalone --prjName baep-sample-host --euiVersion 18.x --envTarget DEV --configEnvTarget cdn-dev --debug --debugNotification --skipNotification --skipGitUpdates --skipInstall

module.exports.run = () => {
  const { prjName, euiVersion, envTarget, configEnvTarget } = utils.tools.getArgs();

  if (!prjName) {
    throw new Error('prjName not provided as pipeline argument');
  }

  if (!euiVersion) {
    throw new Error('euiVersion not provided as pipeline argument');
  }

  if (!envTarget) {
    throw new Error('envTarget OR configEnvTarget not provided as pipeline argument');
  }

  let project, packagesDeps, newVersion;

  return Promise.resolve()
    // START PIPELINE
    .then(() => {
      utils.tools.logVersion();
    })

    // CLONING CONFIG
    .then(() => {
      return configUtils.global.cloneConfig();
    })

    // INITIALIZE HOST, REPOSITORIES and sources injections
    .then(() => {
      return initUtils.initProject.init({
        project: prjName, prjOnly: true, euiVersion: euiVersion, build: true,
      });
    })

    // GETTING THE PROJECT DATA
    .then(() => {
      project = configUtils.projects.getProject(prjName);
    })

    // INIT MESSAGE STACK
    .then(() => {
      // start mailStack
      utils.notification.messageStack.startStack();

      return utils.notification.project.sendProjectMessage({
        project: project,
        text: `:arrow_forward: :arrow_forward: :arrow_forward: :arrow_forward: :arrow_forward: Launching *${project.name}* release for *${envTarget}* environment`,
      });
    })

    // CLONE METADATA REPO
    .then(() => {
      return metadataUtils.common.cloneMetadataRepoStandalone();
    })

    // INSTALL DEPS based on envTarget
    .then(() => {
      // installing the dependencies by composite definition, it's outputting the app package dependencies declared
      // in the dependencies-composite.json file of the project, remapped with the composite declaration per env.
      return installUtils.buildApp.install(project, envTarget);
    })
    .then((deps) => {
      packagesDeps = deps;
    })

    // GETTING NEW VERSION
    .then(() => {
      utils.tools.logTitle('Getting app new version...');
      return versionUtils.app.getNewVersion(project, false, false, envTarget);
    })
    .then((version) => {
      // set the new version found for later use
      newVersion = version;
      utils.tools.logSuccess('New version : ' + newVersion);
    })

    // STORE METADATA
    .then(() => {
      // storing project build metadata
      return metadataUtils.app.storeMetadata(project, newVersion, packagesDeps, envTarget);
    })
    .then(() => {
      return metadataUtils.appEnvs.storeMetadata(project, newVersion, packagesDeps, envTarget);
    })
    .then(() => {
      return metadataUtils.appVersions.storeMetadata(project, newVersion, envTarget);
    })

      // // *****************************************************************
      // // GENERATE MAJOR DIFF REPORT
      // // *****************************************************************
      // .then(() => {
      //   // process v1 - diff report is generated on MASTER / TST release
      //   if (!isSnapshot && !isSupportSnapshotBranch && !envTarget) {
      //     return metadataUtils.appHistory.generateDiffReport(project, newVersion, isSupportBranch);
      //   }

      //   // process v2 - diff report is generated on TST and up
      //   if (envTarget && envTarget !== 'DEV') {
      //     return metadataUtils.appHistory.generateDiffReport(project, newVersion, isSupportBranch, envTarget);
      //   }
      // })

      // // *****************************************************************
      // // STORE APP HISTORY METADATA
      // // *****************************************************************
      // .then((diffMetadata) => {
      //   if (diffMetadata) {
      //     return Promise.resolve()
      //       .then(() => {
      //         return metadataUtils.appHistory.flattenDiffMetadata(diffMetadata);
      //       })

      //       .then((flatDiffMetadata) => {
      //         return utils.notification.project.sendProjectDiffReportMessage(project, flatDiffMetadata);
      //       })
      //   }
      // })

      // // *****************************************************************
      // // STORE APP ASSETS METADATA
      // // *****************************************************************
      // .then((historyMetadata) => {
      //   return metadataUtils.app.storeMetadataAssets(project, newVersion, packagesDeps, historyMetadata, envTargetGen);
      // })




    // BUILD ANGULAR APPLICATION
    .then(() => {
      return utils.buildApp.angular({
        project,
        envTarget,
        isSnapshot: false,
        version: newVersion,
        configEnvTargetin: configEnvTarget,
      });
    })


    // POST BUILD
    .then(() => {
      return utils.buildApp.postBuild(project);
    })

    // DISTRIBUTION OPTIONAL STEP to dynamic S3 buckets
    .then(() => {
      if (project.build && project.build.distribution) {
        return Promise.resolve()
          .then(() => {
            return utils.buildApp.generateProjectDistributionFile(project, false, envTarget);
          })
          .catch((e) => {
            throw e;
          });
      }
    })



    // COMMIT AND PUSH METADATA
    .then(() => {
      const DEVOPS_METADATA_PATH = configUtils.global.getConfigOptions().DEVOPS_METADATA_PATH;
      const message = `chore: update metadata for ${project.name}-${newVersion}`;

      return utils.git.commitAndPush('master', message, DEVOPS_METADATA_PATH);
    })

    // PIPELINE NOTIFICATIONS
    .then(() => {
      return (
        utils.notification.project
          .sendProjectMessage({
            project: project,
            version: newVersion,
            title: '[APPLICATION BUILD SUCCESS]',
            subtitle: 'Successful build of the application! :)',
          })

          // store package config in the root folder to send config to gitlab
          .then(() => {
            return utils.notification.config.storeProjectConfig(project);
          })

          .then(() => {
            utils.notification.messageStack.endStack();
          })
      );
    })

    .catch((e) => {
      utils.tools.logError(`ERROR!!!! - ${e.message}`);
      console.log(e);

      return (
        utils.notification.project
          .sendProjectMessage({
            project: project,
            exception: e,
            title: '[APPLICATION BUILD FAILED]',
            subtitle: 'Error building the App container application! :(',
          })

          // store package config in the root folder to send config to gitlab
          .then(() => {
            return utils.notification.config.storeProjectConfig(project);
          })
          .then(() => {
            utils.notification.messageStack.endStack();
            return utils.notification.messageStack.sendProjectMessage(project);
          })

          .then(() => {
            process.exit(1);
          })
      );
    })
};
