"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.importSqlCheckStatus = importSqlCheckStatus;
exports.default = void 0;

var _chalk = _interopRequireDefault(require("chalk"));

var _graphqlTag = _interopRequireDefault(require("graphql-tag"));

var _debug = _interopRequireDefault(require("debug"));

var _singleLineLog = require("single-line-log");

var _api = _interopRequireDefault(require("../api"));

var _format = require("../cli/format");

var _dbFileImport = require("./db-file-import");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * 
 * @format
 */

/**
 * External dependencies
 */

/**
 * Internal dependencies
 */
const debug = (0, _debug.default)('vip:lib/site-import/status');
const IMPORT_SQL_PROGRESS_POLL_INTERVAL = 5000;
const IMPORT_SQL_PROGRESS_QUERY = (0, _graphqlTag.default)`
	query App($id: Int) {
		app(id: $id) {
			environments {
				id
				jobs {
					id
					type
					createdAt
					progress {
						status
						steps {
							name
							status
						}
					}
				}
				importStatus {
					dbOperationInProgress
					importInProgress
					progress {
						started_at
						steps {
							name
							started_at
							finished_at
							result
							output
						}
						finished_at
					}
				}
			}
		}
	}
`;

async function getStatus(api, appId, envId) {
  const response = await api.query({
    query: IMPORT_SQL_PROGRESS_QUERY,
    variables: {
      id: appId
    },
    fetchPolicy: 'network-only'
  });
  const {
    data: {
      app: {
        environments
      }
    }
  } = response;
  const {
    importStatus,
    jobs
  } = environments.find(e => e.id === envId);
  const importJob = jobs.find(({
    type
  }) => type === 'sql_import');
  return {
    importStatus,
    importJob
  };
}

function getErrorMessage(importFailed) {
  debug({
    importFailed
  });

  let message = _chalk.default.red(`Error: ${importFailed.error}`);

  if (importFailed.inImportProgress) {
    switch (importFailed.stepName) {
      case 'import_preflights':
      case 'validating_sql':
        message += `
This error occurred prior to the mysql batch script processing of your SQL file.

Your site content was not altered.

Please inspect your input file and make the appropriate corrections before trying again.
`;
        break;

      case 'importing_db':
        message += `
This error occurred during the mysql batch script processing of your SQL file.

Your site is ${_chalk.default.blue('automatically being rolled back')} to the last backup prior to your import job.
`;

        if (importFailed.commandOutput) {
          const commandOutput = [].concat(importFailed.commandOutput).join(';');
          message += `
Please inspect your input file and make the appropriate corrections before trying again.
The database server said:
> ${_chalk.default.red(commandOutput)}
`;
        } else {
          message += 'Please contact support and include this message along with your sql file.';
        }

        break;

      default:
    }
  }

  return message;
}

async function importSqlCheckStatus({
  app,
  env
}) {
  const api = await (0, _api.default)();

  if (!(0, _dbFileImport.currentUserCanImportForApp)(app)) {
    throw new Error('The currently authenticated account does not have permission to view SQL import status.');
  }

  const runningSprite = new _format.RunningSprite();

  const getResults = () => new Promise((resolve, reject) => {
    const checkStatus = async () => {
      const {
        importStatus,
        importJob
      } = await getStatus(api, app.id, env.id);
      debug({
        importJob
      });

      if (!importJob) {
        return resolve('No import job found');
      }

      const {
        // completedAt, TODO when Parker support is present
        createdAt,
        progress: {
          status: jobStatus,
          steps
        }
      } = importJob;
      const {
        dbOperationInProgress,
        importInProgress,
        progress: importStepProgress
      } = importStatus;
      debug({
        createdAt,
        dbOperationInProgress,
        importInProgress,
        importStepProgress
      });

      if (importStepProgress.started_at && importStepProgress.started_at * 1000 > new Date(createdAt).getTime()) {
        // The contents of the `import_progress` meta are pertinent to the most recent import job
        const failedImportStep = importStepProgress.steps.find(step => {
          step.result === 'failed' && debug({
            failedStep: step,
            sa: 1000 * step.started_at,
            ca: new Date(createdAt).getTime()
          });
          return step.result === 'failed' && 1000 * step.started_at > new Date(createdAt).getTime();
        });

        if (failedImportStep) {
          return reject({
            inImportProgress: true,
            commandOutput: failedImportStep.output,
            error: 'Import step failed',
            stepName: failedImportStep.name,
            errorText: failedImportStep.error
          });
        }
      }

      if (jobStatus === 'error') {
        return reject({
          error: 'Import job failed',
          steps
        });
      }

      if (!steps.length) {
        return reject({
          error: 'Could not enumerate the import job steps'
        });
      }

      (0, _singleLineLog.stdout)(`
SQL Import Job Started at ${createdAt} (${new Date(createdAt)})

Status:
${(0, _format.formatJobSteps)(steps, runningSprite)}`);

      if (jobStatus !== 'running') {
        return resolve(importJob);
      }

      setTimeout(checkStatus, IMPORT_SQL_PROGRESS_POLL_INTERVAL);
    }; // Kick off the check


    checkStatus();
  });

  try {
    const results = await getResults(); // break out of the singleLogLine

    console.log('\n');

    if (typeof results === 'string') {
      // This type of result is not an importing error. e.g. no import job was found
      console.log(results);
      process.exit(0);
    }

    const {
      progress: {
        status
      }
    } = results;
    console.log(`=============================================================
Result: ${status}
`);
  } catch (importFailed) {
    console.log(`
Result: ${_chalk.default.red('Failed')}
${getErrorMessage(importFailed)}
`);
    process.exit(1);
  }
}

var _default = {
  importSqlCheckStatus
};
exports.default = _default;