#!/usr/bin/env python3
# Copyright 2021 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""Generates benchmark results as pull request comments.

This script is meant to be used by CI and uses pip package "markdown_strings".
"""

import sys
import pathlib

# Add build_tools python dir to the search path.
sys.path.insert(0, str(pathlib.Path(__file__).parent.with_name("python")))

import argparse
import dataclasses
import json
from typing import Any, Dict, Optional, Set, Tuple

import markdown_strings as md
import requests

from common import benchmark_definition, benchmark_presentation, common_arguments
from reporting import benchmark_comment

GITHUB_IREE_REPO_PREFIX = "https://github.com/iree-org/iree"
IREE_DASHBOARD_URL = "https://perf.iree.dev/apis/v2"
IREE_PROJECT_ID = 'IREE'
# The maximal numbers of trials when querying base commit benchmark results.
MAX_BASE_COMMIT_QUERY_COUNT = 10
# The max number of rows to show per table.
TABLE_SIZE_CUT = 3
THIS_DIRECTORY = pathlib.Path(__file__).resolve().parent


@dataclasses.dataclass(frozen=True)
class CommentDef(object):
  title: str
  type_id: str


# Map from comment type to comment definition.
COMMENT_DEF_MAP = {
    "android-benchmark-summary":
        CommentDef(title="Abbreviated Android Benchmark Summary",
                   type_id="bf8cdf94-a992-466d-b11c-778cbd805a22"),
    "linux-benchmark-summary":
        CommentDef(title="Abbreviated Linux Benchmark Summary",
                   type_id="37549014-3c67-4e74-8d88-8e929231abe3"),
    "benchmark-summary":
        CommentDef(title="Abbreviated Benchmark Summary",
                   type_id="5b42cbfe-26a0-4164-a51c-07f06762e2dc")
}


def get_git_total_commit_count(commit: str, verbose: bool = False) -> int:
  """Gets the total commit count in history ending with the given commit."""
  # TODO(#11703): Should use --first-parent here. See issue for the required
  # work.
  count = benchmark_definition.execute_cmd_and_get_output(
      ['git', 'rev-list', '--count', commit],
      cwd=THIS_DIRECTORY,
      verbose=verbose)
  return int(count)


def get_from_dashboard(url: str,
                       payload: Dict[str, Any],
                       verbose: bool = False) -> Dict[str, Dict[str, Any]]:
  headers = {'Content-type': 'application/json'}
  data = json.dumps(payload)

  if verbose:
    print(f'API request payload: {data}')

  response = requests.get(url, data=data, headers=headers)
  code = response.status_code
  if code != 200:
    raise requests.RequestException(
        f'Failed to get from dashboard server with status code {code}')

  data = response.json()
  if verbose:
    print(f'Queried base benchmark data: {data}')
  return data


BenchmarkQueryResults = Dict[str, Dict[str, Any]]


def query_base_benchmark_results(
    commit: str, verbose: bool = False) -> BenchmarkQueryResults:
  """Queries the benchmark results for the given commit."""
  build_id = get_git_total_commit_count(commit, verbose)
  payload = {'projectId': IREE_PROJECT_ID, 'buildId': build_id}
  return get_from_dashboard(f'{IREE_DASHBOARD_URL}/getBuild',
                            payload,
                            verbose=verbose)


@dataclasses.dataclass(frozen=True)
class ComparableBenchmarkResults(object):
  commit_sha: str
  benchmark_results: BenchmarkQueryResults


def _find_comparable_benchmark_results(
    start_commit: str,
    required_benchmark_keys: Set[str],
    verbose: bool = False) -> Optional[ComparableBenchmarkResults]:
  cmds = [
      "git", "rev-list", "--first-parent",
      f"--max-count={MAX_BASE_COMMIT_QUERY_COUNT}", start_commit
  ]
  output = benchmark_definition.execute_cmd_and_get_output(cmds,
                                                           cwd=THIS_DIRECTORY,
                                                           verbose=verbose)
  previous_commits = output.splitlines()
  # Try to query some base benchmark to diff against, from the top of the
  # tree. Bail out if the maximal trial number is exceeded.
  for base_commit in previous_commits:
    base_benchmarks = query_base_benchmark_results(commit=base_commit,
                                                   verbose=verbose)
    base_benchmark_keys = set(base_benchmarks.keys())
    if required_benchmark_keys <= base_benchmark_keys:
      return ComparableBenchmarkResults(commit_sha=base_commit,
                                        benchmark_results=base_benchmarks)

  return None


def _get_git_commit_hash(ref: str, verbose: bool = False) -> str:
  """Gets the commit hash for the given commit."""
  return benchmark_definition.execute_cmd_and_get_output(
      ['git', 'rev-parse', ref], cwd=THIS_DIRECTORY, verbose=verbose)


def _get_git_merge_base_commit(pr_commit: str,
                               target_branch: str,
                               verbose: bool = False) -> str:
  return benchmark_definition.execute_cmd_and_get_output(
      args=["git", "merge-base", target_branch, pr_commit],
      cwd=THIS_DIRECTORY,
      verbose=verbose)


def _get_benchmark_result_markdown(
    execution_benchmarks: Dict[
        str, benchmark_presentation.AggregateBenchmarkLatency],
    compilation_metrics: Dict[str, benchmark_presentation.CompilationMetrics],
    pr_url: str, build_url: str, comment_def: CommentDef,
    commit_info_md: str) -> Tuple[str, str]:
  """Gets the full/abbreviated markdown summary of all benchmarks in files."""

  pr_info = md.link("Pull request", pr_url)
  build_info = md.link("Build", build_url)

  # Compose the full benchmark tables.
  full_table = [md.header("Full Benchmark Summary", 2)]
  full_table.append(md.unordered_list([commit_info_md, pr_info, build_info]))

  # Compose the abbreviated benchmark tables.
  abbr_table = [md.header(comment_def.title, 2)]
  abbr_table.append(commit_info_md)

  if len(execution_benchmarks) > 0:
    full_table.append(
        benchmark_presentation.categorize_benchmarks_into_tables(
            execution_benchmarks))

    abbr_benchmarks_tables = benchmark_presentation.categorize_benchmarks_into_tables(
        execution_benchmarks, TABLE_SIZE_CUT)
    if len(abbr_benchmarks_tables) == 0:
      abbr_table.append("No improved or regressed benchmarks 🏖️")
    else:
      abbr_table.append(abbr_benchmarks_tables)

  # Compose the full compilation metrics tables.
  if len(compilation_metrics) > 0:
    full_table.append(
        benchmark_presentation.categorize_compilation_metrics_into_tables(
            compilation_metrics))

    abbr_compilation_metrics_tables = benchmark_presentation.categorize_compilation_metrics_into_tables(
        compilation_metrics, TABLE_SIZE_CUT)
    if len(abbr_compilation_metrics_tables) == 0:
      abbr_table.append("No improved or regressed compilation metrics 🏖️")
    else:
      abbr_table.append(abbr_compilation_metrics_tables)

  abbr_table.append("For more information:")
  # We don't know until a Gist is really created. Use a placeholder for now and
  # replace later.
  full_result_info = md.link("Full benchmark result tables",
                             benchmark_comment.GIST_LINK_PLACEHORDER)
  abbr_table.append(md.unordered_list([full_result_info, build_info]))

  # Append the unique comment type id to help identify and update the existing
  # comment.
  abbr_table.append(f"<!--Comment type id: {comment_def.type_id}-->")

  return "\n\n".join(full_table), "\n\n".join(abbr_table)


def parse_arguments():
  """Parses command-line options."""

  parser = argparse.ArgumentParser()
  parser.add_argument(
      "--benchmark_files",
      metavar="<benchmark-json-files>",
      default=[],
      nargs="+",
      help=("Paths to the JSON files containing benchmark results, "
            "accepts wildcards"))
  parser.add_argument(
      "--compile_stats_files",
      metavar="<compile-stats-json-files>",
      default=[],
      nargs="+",
      help=("Paths to the JSON files containing compilation statistics, "
            "accepts wildcards"))
  parser.add_argument("--pr_number", required=True, type=int, help="PR number")
  parser.add_argument("--pr_committish",
                      type=str,
                      default="HEAD",
                      help="PR commit hash or ref")
  parser.add_argument("--pr_base_branch",
                      type=str,
                      default=None,
                      help="Base branch to merge the PR.")
  parser.add_argument("--comment_type",
                      required=True,
                      choices=COMMENT_DEF_MAP.keys(),
                      help="Type of summary comment")
  parser.add_argument("--build_url",
                      required=True,
                      type=str,
                      help="CI build page url to show in the report")
  parser.add_argument("--output", type=pathlib.Path, default=None)
  parser.add_argument("--verbose",
                      action="store_true",
                      help="Print internal information during execution")

  return parser.parse_args()


def main(args):
  benchmark_files = common_arguments.expand_and_check_file_paths(
      args.benchmark_files)
  compile_stats_files = common_arguments.expand_and_check_file_paths(
      args.compile_stats_files)

  pr_commit = _get_git_commit_hash(ref=args.pr_committish, verbose=args.verbose)
  execution_benchmarks = benchmark_presentation.aggregate_all_benchmarks(
      benchmark_files=benchmark_files, expected_pr_commit=pr_commit)
  compilation_metrics = benchmark_presentation.collect_all_compilation_metrics(
      compile_stats_files=compile_stats_files, expected_pr_commit=pr_commit)

  if args.pr_base_branch is None:
    pr_base_commit = None
  else:
    pr_base_commit = _get_git_merge_base_commit(
        pr_commit=pr_commit,
        target_branch=args.pr_base_branch,
        verbose=args.verbose)

  if pr_base_commit is None:
    comparable_results = None
  else:
    required_benchmark_keys = set(execution_benchmarks.keys())
    for target_id in compilation_metrics:
      for mapper in benchmark_presentation.COMPILATION_METRICS_TO_TABLE_MAPPERS:
        required_benchmark_keys.add(mapper.get_series_id(target_id))

    comparable_results = _find_comparable_benchmark_results(
        start_commit=pr_base_commit,
        required_benchmark_keys=required_benchmark_keys,
        verbose=args.verbose)

  if comparable_results is None:
    comparable_commit = None
  else:
    comparable_commit = comparable_results.commit_sha
    # Update the execution benchmarks with base numbers.
    for bench in execution_benchmarks:
      base_benchmark = comparable_results.benchmark_results[bench]
      if base_benchmark["sampleUnit"] != "ns":
        raise ValueError("Only support nanoseconds for latency sample.")
      execution_benchmarks[bench].base_mean_time = base_benchmark["sample"]

    # Update the compilation metrics with base numbers.
    for target_id, metrics in compilation_metrics.items():
      updated_metrics = metrics
      for mapper in benchmark_presentation.COMPILATION_METRICS_TO_TABLE_MAPPERS:
        base_benchmark = comparable_results.benchmark_results[
            mapper.get_series_id(target_id)]
        if base_benchmark["sampleUnit"] != mapper.get_unit():
          raise ValueError("Unit of the queried sample is mismatched.")
        updated_metrics = mapper.update_base_value(updated_metrics,
                                                   base_benchmark["sample"])
      compilation_metrics[target_id] = updated_metrics

  pr_commit_link = md.link(pr_commit,
                           f"{GITHUB_IREE_REPO_PREFIX}/commit/{pr_commit}")
  commit_info_md = f"@ commit {pr_commit_link}"
  if comparable_commit is not None:
    baseline_commit_link = md.link(
        comparable_commit,
        f"{GITHUB_IREE_REPO_PREFIX}/commit/{comparable_commit}")
    commit_info_md += f" (vs. base {baseline_commit_link})"
  elif pr_base_commit is not None:
    commit_info_md += " (no previous benchmark results to compare)"

  comment_def = COMMENT_DEF_MAP[args.comment_type]
  full_md, abbr_md = _get_benchmark_result_markdown(
      execution_benchmarks=execution_benchmarks,
      compilation_metrics=compilation_metrics,
      pr_url=f"{GITHUB_IREE_REPO_PREFIX}/pull/{args.pr_number}",
      build_url=args.build_url,
      comment_def=comment_def,
      commit_info_md=commit_info_md)

  comment_data = benchmark_comment.CommentData(
      type_id=comment_def.type_id,
      abbr_md=abbr_md,
      full_md=full_md,
      unverified_pr_number=args.pr_number)
  comment_json_data = json.dumps(dataclasses.asdict(comment_data), indent=2)
  if args.output is None:
    print(comment_json_data)
  else:
    args.output.write_text(comment_json_data)


if __name__ == "__main__":
  main(parse_arguments())
