const { matchesSemver, isPinnedVersion } = require('../../../util/semver');
const ghGot = require('../../../platform/github/gh-got-wrapper');

module.exports = {
  getChangeLogJSON,
};

async function getTags(repository) {
  try {
    const versions = {};

    const res = await ghGot(`repos/${repository}/tags?per_page=100`, {
      paginate: true,
    });

    const tags = (res && res.body) || [];

    if (!tags.length) {
      logger.debug({ repository }, 'repository has no Github tags');
    }

    tags.forEach(tag => {
      const version = isPinnedVersion(tag.name);
      if (version) {
        versions[version] = { gitHead: tag.name };
      }
    });
    return versions;
  } catch (err) {
    logger.info({ sourceRepo: repository }, 'Failed to fetch Github tags');
    logger.debug({
      err,
      message: err.message,
      body: err.response ? err.response.body : undefined,
    });
    return {};
  }
}

async function getRepositoryHead(repository, version) {
  if (version.gitHead) {
    return version.gitHead;
  }
  if (!version.date) {
    return null;
  }
  logger.trace({ repository, version }, 'Looking for commit SHA by date');
  try {
    const res = await ghGot(`repos/${repository}/commits/@{${version.date}}`);
    const commit = res && res.body;
    return commit && commit.sha;
  } catch (err) {
    logger.debug({ err, repository }, 'Failed to fetch Github commit by date');
    return null;
  }
}

async function getChangeLogJSON({
  githubBaseURL,
  repositoryUrl,
  fromVersion,
  newVersion,
  versions,
}) {
  logger.debug('Checking for github source URL manually');
  const semverString = `>${fromVersion} <=${newVersion}`;
  logger.trace(`semverString: ${semverString}`);
  if (!(repositoryUrl && repositoryUrl.startsWith(githubBaseURL))) {
    logger.debug('No repo found manually');
    return null;
  }
  logger.debug({ url: repositoryUrl }, 'Found github URL manually');
  const repository = repositoryUrl
    .replace(githubBaseURL, '')
    .replace(/#.*/, '');
  if (repository.split('/').length !== 2) {
    logger.debug('Invalid github URL found');
    return null;
  }

  const tags = await getTags(repository);

  function getHead(version) {
    return getRepositoryHead(repository, {
      ...version,
      ...tags[version.version],
    });
  }

  const releases = [];

  // compare versions
  for (let i = 1; i < versions.length; i += 1) {
    const prev = versions[i - 1];
    const next = versions[i];
    if (matchesSemver(next.version, semverString)) {
      const release = {
        version: next.version,
        date: next.date,
        // put empty changes so that existing templates won't break
        changes: [],
        compare: {},
      };
      const prevHead = await getHead(prev);
      const nextHead = await getHead(next);
      if (prevHead && nextHead) {
        release.compare.url = `${githubBaseURL}${repository}/compare/${prevHead}...${nextHead}`;
      }
      releases.unshift(release);
    }
  }

  const res = {
    project: {
      githubBaseURL,
      github: repository,
      repository: repositoryUrl,
    },
    versions: releases,
  };

  logger.debug({ res }, 'Manual res');
  return res;
}