'use strict';

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

// LOCAL
const tools = require('../../utils/tools');
const configUtils = require('../config/config-utils');
const installUtils = require('../install/install-utils');
const versionUtils = require('../version/version-utils');

// INNER
const innerPackageUtils = require('./package-utils');

// FETCH ARGS
const { dryRun } = tools.getArgs();

const getMetadata = (project) => {
  const DEVOPS_METADATA_PATH = configUtils.global.getConfigOptions().DEVOPS_METADATA_PATH;

  return Promise.resolve()
    .then(() => {
      if (!DEVOPS_METADATA_PATH) {
        throw new Error(`Devops metadata folder ${DEVOPS_METADATA_PATH} NOT FOUND`);
      }

      return tools.getJsonFileContent(path.join(DEVOPS_METADATA_PATH, project.devopsMetadataFile));
    })
    .catch((e) => {
      throw e;
    });
};

const storeMetadata = (project, newVersion, metadata, envTarget) => {
  const appReleaseDate = moment(new Date()).format('DD/MM/YYYY HH:mm');
  const appInfos = `${newVersion} - ${appReleaseDate}`;
  const DEVOPS_METADATA_PATH = configUtils.global.getConfigOptions().DEVOPS_METADATA_PATH;

  return Promise.resolve()
    .then(() => {
      tools.logTitle('Storing application metadata...');

      let generatedMetadata;
      let versions;

      const metadataFile = path.join(DEVOPS_METADATA_PATH, project.devopsMetadataFile);

      if (tools.isFileExists(metadataFile)) {
        generatedMetadata = require(metadataFile);
        versions = generatedMetadata.versions;
      } else {
        generatedMetadata = {};
        versions = [];
      }

      versions.push({
        name: newVersion,
        releaseDate: appReleaseDate,
        infos: appInfos,
        packages: metadata,
        envTarget: envTarget,
      });

      generatedMetadata.versions = versions;

      if (!dryRun) {
        tools.writeJsonFileSync(metadataFile, generatedMetadata);
      }
    })

    .then(() => {
      tools.logSuccess();
    })

    .catch((e) => {
      throw e;
    });
};

const storeMetadataAssets = (project, newVersion, packagesDeps, historyMetadata, envTarget) => {
  const appReleaseDate = moment(new Date()).format('DD/MM/YYYY HH:mm');
  const appInfos = `${newVersion} - ${appReleaseDate}`;

  tools.logTitle('Storing app assets metadata');

  return (
    Promise.resolve()
      // storing metadata file
      .then(() => {
        tools.logInfo('Storing app metadata into project assets');

        const appMetadata = {
          appVersion: newVersion,
          appReleaseDate: appReleaseDate,
          appInfos: appInfos,
          metadata: packagesDeps || {},
        };

        const metadataFile = path.join(project.folder, 'src', 'assets', 'app-metadata.json');

        tools.logInfo(`Creating ${metadataFile}`);
        console.log(appMetadata);

        if (!dryRun) {
          return tools.writeJsonFileSync(metadataFile, appMetadata);
        }
      })

      .then(() => {
        tools.logInfo('Storing app env delta metadata into project assets');

        if (!historyMetadata) {
          tools.logInfo('no history metadata found...skipping');
        } else {
          const metadataFile = path.join(project.folder, 'src', 'assets', 'app-metadata-history.json');

          tools.logInfo(`Creating ${metadataFile}`);

          if (!dryRun && envTarget && envTarget !== 'DEV') {
            return tools.writeJsonFileSync(metadataFile, historyMetadata);
          }
        }
      })

      .catch((e) => {
        throw e;
      })
  );
};

const storeMetadataAssetsStandAlone = () => {
  tools.logTitle('App metadata generation');

  // getting project
  const prj = configUtils.projects.getProject();
  let currentVersion, packageDeps, packageDepsMetadata;

  return (
    Promise.resolve()
      // getting current app version
      .then(() => {
        return versionUtils.app.getCurrentVersion(prj);
      })
      .then((version) => {
        currentVersion = version;
      })

      // getting packages composite deps version
      .then(() => {
        return installUtils.projects.getDeps(prj);
      })
      .then((deps) => {
        packageDeps = deps;

        packageDepsMetadata = Object.keys(deps).map((d) => {
          const pkg = configUtils.packages.getPackageByNpmPkg(d, true);
          tools.logInfo(`getting pkg versions metadata for : ${pkg.name} / version: ${deps[d]}`);
          const pkgVersionMetadata = innerPackageUtils.getVersionMetadata(pkg, deps[d]);

          if (!pkgVersionMetadata) {
            tools.logWarning(`===> version of pkg not found in metadata, probably caused by a failure of the package build`);
          } else {
            return {
              npmPkg: d,
              repository: pkgVersionMetadata.name,
              version: pkgVersionMetadata.version,
              releaseDate: pkgVersionMetadata.date,
            };
          }
        });
      })

      // storing metadata
      .then(() => {
        tools.logInfo('Storing app metadata into project assets');

        const appReleaseDate = moment(new Date()).format('DD/MM/YYYY HH:mm');
        const appInfos = `${currentVersion} - ${appReleaseDate}`;

        const appMetadata = {
          appVersion: currentVersion,
          appReleaseDate: appReleaseDate,
          appInfos: appInfos,
          metadata: packageDeps,
          metadataDetails: packageDepsMetadata,
        };

        const metadataFile = path.join(prj.folder, 'src', 'assets', 'app-metadata.json');

        tools.logInfo(`Creating ${metadataFile}`);
        console.log(JSON.stringify(appMetadata, null, 2));

        if (!dryRun) {
          return tools.writeJsonFileSync(metadataFile, appMetadata);
        }
      })

      .catch((e) => {
        throw e;
      })
  );
};

module.exports = {
  getMetadata,
  storeMetadata,
  storeMetadataAssets,
  storeMetadataAssetsStandAlone,
};
