// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {BuildbucketV2Client} from './buildbucket-client';
import {
    compareBuildIds,
    isCQExperimental,
  } from './buildbucket-utils';
import {ResultDbV1Client} from './resultdb-client';
import {openTryjobPicker} from './cr-tryjob-picker.js';

/**
 * Heads up! Everything in this file is still in flux. The new reboot checks API
 * is still in development. So everything in this file can change. And it is
 * expected that the amount of comments and tests is limited for the time being.
 */
export const CQ_EXPERIMENTAL_TAG = 'CQ_EXPERIMENTAL';

// An ordered list of TestResult statuses from most to least important. Used to
// sort TestResults.
const RESULT_STATUSES = [
  'FAIL',
  'CRASH',
  'ABORT',
  'SKIP',
  'PASS',
];

export class ChecksFetcher {
  constructor(plugin, buildbucketHost, maxVariantsPerBuild) {
    this.plugin = plugin;
    this.project = this.extractProjectFromUrl();
    this.gerritHost = this.extractHostFromUrl();
    this.buildbucketHost = buildbucketHost;
    this.maxVariantsPerBuild = maxVariantsPerBuild;
    this.includeExperiments = false;
  }

  async fetch(changeNumber, patchsetNumber) {
    // Query BuildBucket for build info.
    const gerritChange =
        {
          host: this.gerritHost,
          // TODO(gavinmak): Change Checks API to provide the change object and use
          // change.project instead.
          project: this.project,
          change: changeNumber,
          patchset: patchsetNumber,
        };
    const buildFields = [
      'id',
      'builder',
      'tags',
      'status',
      'critical',
      'createTime',
      'startTime',
      'endTime',
      'summaryMarkdown',
      'infra.resultdb',
      'infra.swarming',
    ];
    const bbClient = new BuildbucketV2Client(this.buildbucketHost);
    const result = await bbClient.batch({
      requests: [{
        searchBuilds: {
          pageSize: 500,
          predicate: {gerritChanges: [gerritChange]},
          fields: buildFields.map(f => `builds.*.${f}`).join(','),
        },
      }],
    });
    let allBuilds = result.responses.map(r => r.searchBuilds.builds || []).flat();
    if (!this.includeExperiments) {
      allBuilds = allBuilds.filter(build => !isCQExperimental(build));
    }
    allBuilds.sort((a, b) => -compareBuildIds(a.id, b.id));

    // Query ResultDB for unexpected TestVariants.
    const rdbResults = await Promise.allSettled(
        allBuilds.map(build => this.fetchUnexpectedTestVariants(build)));

    const runs = [];
    const attempts = this.createAttemptList(allBuilds);
    allBuilds.forEach((build, i) => {
      const result = rdbResults[i];
      if (result.status === 'rejected') {
        console.error(result.reason);
      }

      const run = this.convertBuildToRun(
        build,
        patchsetNumber,
        attempts,
        result.value || [],
      );

      if (run) {
        runs.push(run);
      }
    });

    return {
      responseCode: 'OK',
      actions: [
        {
          name: 'Choose Tryjobs',
          callback: this.chooseTryjobsCallback.bind(this),
        },
        {
          name: `${this.includeExperiments ? 'Hide' : 'Show'} Experimental Results`,
          callback: this.filterExperimentsCallback.bind(this),
        },
      ],
      runs,
    };
  }

  /**
   * Returns all TestVariants for the given build whose status is not EXPECTED.
   */
  async fetchUnexpectedTestVariants(build) {
    const rdbInfo = build.infra.resultdb;
    const rdbClient = new ResultDbV1Client(rdbInfo.hostname);
    const variants = [];
    const pageSize = 1000;
    let pageToken = '';

    // queryTestVariants returns all UNEXPECTED, FLAKY, and EXONERATED
    // TestVariants before returning EXPECTED TestVariants.
    while (true) {
      const response = await rdbClient.queryTestVariants({
        invocations: [rdbInfo.invocation],
        pageSize: pageSize,
        pageToken: pageToken,
      });

      // Exit if there are no unexpected TestVariants.
      if (!response.testVariants || response.testVariants.length === 0) {
        break;
      }
      if (response.testVariants[0].status === 'EXPECTED') {
        break;
      }
      variants.push(...response.testVariants);

      // Exit if there are no more unexpected TestVariants to fetch.
      if (response.testVariants.length < pageSize || !response.nextPageToken) {
        break;
      }
      pageToken = response.nextPageToken;
    }
    return variants;
  }

  /**
   * Converts a Buildbucket `Build` object into a Reboot Checks API `Run` object.
   */
  convertBuildToRun(build, patchset, attempts, unexpectedTestVariants) {
    if (!build || !build.builder || !build.builder.builder) return undefined;
    const buildLink = this.createBuildLink(this.buildbucketHost, build.id);
    const buildResourceName = this.buildbucketResourceName(this.buildbucketHost, build.id);
    const actions = this.createActions(build);

    const run = {
      patchset: patchset,
      attempt: attempts[build.builder.builder].indexOf(build.id) + 1,
      externalId: buildResourceName,
      checkName: build.builder.builder,
      checkLink: this.createBuilderLink(build),
      status: this.getRunStatusFromBuild(build),
      statusDescription: build.status,
      statusLink: buildLink,
      actions: actions,
      scheduledTimestamp: build.createTime,
      startedTimestamp: build.startTime,
      finishedTimestamp: build.endTime,
      results: [],
    };

    // There are no CheckResults for SCHEDULED builds.
    if (build.status === 'SCHEDULED') {
      return run;
    }

    // Create a CheckResult for the Buildbucket build.
    const buildCategory = this.getResultCategoryFromBuild(build);
    const buildIsExperimental = isCQExperimental(build);

    const commonTags = [];
    buildIsExperimental && commonTags.push(CQ_EXPERIMENTAL_TAG);

    // To minimize clutter for the user, SUCCESSful builds should not contain the
    // Buildbucket CheckResult. Relevant information should be put in the CheckRun object.
    if (build.status !== 'SUCCESS') {
      run.results.push({
        externalId: buildResourceName,
        category: buildCategory,
        summary: `Build ${build.status}`,
        message: build.summaryMarkdown || '',
        tags: commonTags,
        links: [
          {
            url: buildLink,
            primary: true,
          },
          {
            url: this.createBuildTaskLink(build) || '',
            primary: true,
          },
        ],
        actions: actions,
      });
    }

    if (unexpectedTestVariants) {
      // Create a CheckResult for each TestVariant. Limit the number created to
      // this.maxVariantsPerBuild.
      const numDisplayed = Math.min(unexpectedTestVariants.length, this.maxVariantsPerBuild);
      unexpectedTestVariants.slice(0, numDisplayed).forEach((variant) => {
        const result = {
          category: this.getResultCategoryFromVariant(variant, build),
          summary: variant.testId, // TODO(gavinmak): Replace with testMetadata.
          tags: commonTags,
          // TODO(crbug.com/1163705): Add links to the specific test.
          links: [
            {
              url: buildLink,
              primary: false,
            },
          ],
          actions: actions,
        };

        if (variant.status === 'FLAKY') {
          // Remove duplicate results with identical summaryHtmls.
          variant.results = [
            ...new Map(variant.results.map(r => [r.result.summaryHtml, r])).values(),
          ];

          // Sort results by status from most to least important.
          variant.results.sort((a, b) => {
            return RESULT_STATUSES.indexOf(a.result.status) - RESULT_STATUSES.indexOf(b.result.status);
          });

          // TODO(gavinmak): Wrap summaryHtml with <p> when Gerrit supports HTML messages.
          result.message = variant.results.map(r => r.result.summaryHtml).join('\n');
        } else {
          result.message = variant.results[0].result.summaryHtml;
        }

        result.links.push({
          url: this.createTestTaskLink(variant.results[0].result) || '',
          primary: false,
        });

        run.results.push(result);
      });

      // Create a CheckResult to direct to additional failures.
      if (unexpectedTestVariants.length > this.maxVariantsPerBuild) {
        const numExtraResults = unexpectedTestVariants.length - this.maxVariantsPerBuild;
        run.results.push({
          category: buildIsExperimental ? 'INFO' : 'ERROR',
          summary: build.builder.builder,
          message: `${numExtraResults} more test${numExtraResults > 1 ? 's' : ''} failed`,
          tags: commonTags,
          links: [
            {
              url: buildLink,
              primary: false,
            },
          ],
          actions: actions,
        });
      }
    }
    return run;
  }

  /**
   * Returns a CheckRun status from a Buildbucket build.
   */
  getRunStatusFromBuild(build) {
    switch (build.status) {
      case 'SCHEDULED':
      case 'STARTED':
        return 'RUNNING';
      case 'SUCCESS':
      case 'FAILURE':
      case 'CANCELED':
      case 'INFRA_FAILURE':
        return 'COMPLETED';
      default:
        return 'RUNNABLE';
    }
  }

  /**
   * Returns a CheckResult category from a Buildbucket build.
   */
  getResultCategoryFromBuild(build) {
    if (['SCHEDULED', 'CANCELED', 'STARTED', 'SUCCESS'].includes(build.status) ||
        isCQExperimental(build)) {
      return 'INFO';
    } else if (build.critical === 'NO') {
      return 'WARNING';
    } else {
      return 'ERROR';
    }
  }

  /**
   * Returns a CheckResult category from a TestVariant and Buildbucket build.
   */
  getResultCategoryFromVariant(variant, build) {
    const status = variant.status;
    if (status === 'EXPECTED' || isCQExperimental(build)) {
      return 'INFO';
    } else if (['EXONERATED', 'FLAKY'].includes(status)) {
      return 'WARNING';
    } else {
      return 'ERROR';
    }
  }

  /**
  * Returns a link to the Swarming build task.
  */
  createBuildTaskLink(build) {
    const swarming = build.infra.swarming;
    return swarming && `https://${swarming.hostname}/task?id=${swarming.taskId}`;
  }

  /**
  * Returns a link to the Swarming test task.
  */
  createTestTaskLink(testResult) {
    const match = /^invocations\/task-([a-zA-Z\-\.]+\.com)-(\w+)/.exec(testResult.name);
    return match && `https://${match[1]}/task?id=${match[2]}`;
  }

  /**
  * Returns a link to the builder page for the given build.
  */
  createBuilderLink(build) {
    const builder = build.builder;
    return `https://ci.chromium.org/p/${builder.project}/builders/` +
        `${builder.bucket}/${builder.builder}`;
  }

  /**
   * Returns a link to the build page for a given Buildbucket host and buildId.
   */
  createBuildLink(host, buildId) {
    return 'https:' + this.buildbucketResourceName(host, buildId);
  }

  /**
   * Returns the full resource name for a given Buildbucket host and buildId.
   */
  buildbucketResourceName(host, buildId) {
    return `//${host}/build/${buildId}`;
  }

  /**
  * Returns true if the given object is empty.
  */
  isEmpty(obj) {
    return !obj || Object.keys(obj).length === 0;
  }

  /**
   * Returns a dictionary mapping builders to an ordered list of build ids.
   */
  createAttemptList(builds) {
    const dct = {};
    builds.forEach(build => {
      const name = build.builder.builder;
      if (!(name in dct)) {
        dct[name] = [build.id];
      } else {
        dct[name].push(build.id);
      }
    });
    Object.values(dct).forEach((arr) => arr.sort(compareBuildIds));
    return dct;
  }

  /**
   * Returns a list of actions used in a Reboot Checks API `Run` object.
   */
  createActions(build) {
    const actions = [
      {
        name: 'Run',
        tooltip: 'Start a new builder run and cancel an existing run if it exists',
        primary: false,
        callback: this.startRunCallback.bind(this),
      },
    ];

    if (['SCHEDULED', 'STARTED'].includes(build.status)) {
      actions.push({
        name: 'Cancel',
        tooltip: 'Cancel existing runs',
        primary: false,
        callback: this.cancelRunCallback.bind(this),
      });
    }

    return actions;
  }

  /**
   * ActionCallback that cancels an existing run and starts a new builder run via Buildbucket.
   */
  async startRunCallback(change, patchset, attempt, externalId, checkName, actionName) {
    await this.cancelRunCallback(change, patchset, attempt, externalId, checkName, actionName);
    const gerritChange =
        {
          host: this.gerritHost,
          // TODO(gavinmak): Change Checks API to provide the change object and use
          // change.project instead.
          project: this.project,
          change: change,
          patchset: patchset,
        };
    const client = new BuildbucketV2Client(this.buildbucketHost);
    await client.scheduleBuild({
      // TODO(gavinmak): Add request ID.
      templateBuildId: this.extractBuildbucketId(externalId),
      gerritChanges: [gerritChange],
    });
    return {};
  }

  /**
   * ActionCallback that cancels an existing build. If the build is in an end state, this is a
   * no-op.
   */
  async cancelRunCallback(change, patchset, attempt, externalId, checkName, actionName) {
    const client = new BuildbucketV2Client(this.buildbucketHost);
    await client.cancelBuild({
      id: this.extractBuildbucketId(externalId),
      summaryMarkdown: 'Cancel build',
    });
    return {};
  }

  /**
   * Top-Level ActionCallback that opens the tryjob picker popup.
   */
  async chooseTryjobsCallback(change, patchset, attempt, externalId, checkName, actionName) {
    // TODO(gavinmak): When Checks API uses the change object, use change.project instead.
    const project = encodeURIComponent(this.project);
    const pluginName = encodeURIComponent(this.plugin.getPluginName());
    const pluginConfig = await this.plugin.restApi().get(
      `/projects/${project}/${pluginName}~config`);
    await openTryjobPicker(
        this.plugin, pluginConfig, this.buildbucketHost, project, change, patchset);
    this.plugin.checks().announceUpdate();
    return {};
  }

  /**
   * Top-Level ActionCallback that toggles the display and fetching of experimental builds,
   * CheckRuns, and CheckResults.
   */
  async filterExperimentsCallback(change, patchset, attempt, externalId, checkName, actionName) {
    this.includeExperiments = !this.includeExperiments;
    this.plugin.checks().announceUpdate();
    return {};
  }

  /**
   * Returns the ID to use for buildbucket RPCs. Assumes externalId is a full resource name
   * which takes the format "//${host}/build/${buildId}"
   */
  extractBuildbucketId(externalId) {
    const match = /build\/(\d+)$/.exec(externalId);
    return match && match[1];
  }

  /**
   * Returns the host from the current URL's path.
   */
  extractHostFromUrl() {
    return window.location.host;
  }

  /**
   * Returns the project from the current URL's path.
   *
   * TODO(gavinmak): Remove this function when Gerrit checks uses a change object.
   */
  extractProjectFromUrl() {
    const match = /^\/c\/([^\+]+)\/\+/.exec(window.location.pathname);
    return match && match[1];
  }
}
