#!/usr/bin/env python3
#
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import os
import re
import subprocess
import sys
import shutil
from typing import Optional

# Color codes
RED = '\033[0;31m'
GREEN = '\033[0;32m'
YELLOW = '\033[0;33m'
NC = '\033[0m'  # No Color

# Constants for paths. Assumes the script is run from the repository root.
SETUP_PY_PATH = 'python/setup.py'
VENV_PYTHON = os.path.abspath('.venv/bin/python')


def info(msg: str) -> None:
  print(f"{GREEN}INFO:{NC} {msg}")


def warn(msg: str) -> None:
  print(f"{YELLOW}WARN:{NC} {msg}")


def error(msg: str) -> None:
  print(f"{RED}ERROR:{NC} {msg}", file=sys.stderr)
  sys.exit(1)


def prompt(msg: str) -> str:
  return input(f"{YELLOW}ACTION:{NC} {msg}")


def confirm(msg: str) -> None:
  reply = input(f"{msg} [y/N] ").lower().strip()
  if reply not in ['y', 'yes']:
    error("Aborted by user.")


def run_cmd(*args: str, check: bool = True, cwd: Optional[str] = None) -> None:
  info(f"Running command: {' '.join(args)}")
  subprocess.run(args, check=check, cwd=cwd)


def check_git_clean() -> None:
  """Checks if the git working directory is clean."""
  info("Checking for clean git working directory...")
  try:
    subprocess.check_call(['git', 'diff', '--quiet'])
    subprocess.check_call(['git', 'diff', '--cached', '--quiet'])
  except subprocess.CalledProcessError:
    error("Git working directory is not clean. Please commit or stash changes.")
  info("Git working directory is clean.")


def get_current_branch() -> str:
  """Returns the current git branch."""
  return subprocess.check_output(['git', 'rev-parse', '--abbrev-ref',
                                  'HEAD']).decode('utf-8').strip()


def get_setup_py_content() -> str:
  with open(SETUP_PY_PATH, 'r') as f:
    return f.read()


def write_setup_py_content(content: str) -> None:
  with open(SETUP_PY_PATH, 'w') as f:
    f.write(content)


def get_current_version(content: str) -> str:
  """Extracts version from setup.py using a robust regex."""
  match = re.search(r"version\s*=\s*'([^']*)'", content)
  if not match:
    error(f"Could not find version in {SETUP_PY_PATH}")
    sys.exit(1)  # Unreachable, but satisfies type checker
  return match.group(1)


def bump_version() -> None:
  """Stage 1: Creates a commit with a bumped version number."""
  info("--- Stage 1: Bumping version ---")
  content = get_setup_py_content()
  current_version = get_current_version(content)
  info(f"Current version is {current_version}")

  new_version = prompt("Enter the new version (e.g., X.Y.Z): ")
  if not re.match(r'\d+\.\d+\.\d+', new_version):
    error("Invalid version format. Please use 'X.Y.Z'.")

  branch_name = prompt("Enter a name for the new release branch: ")
  run_cmd('git', 'checkout', '-b', branch_name)

  info(f"Updating version in {SETUP_PY_PATH} to {new_version}...")
  new_content = re.sub(r"version\s*=\s*'[^']*'", f"version='{new_version}'",
                       content)
  write_setup_py_content(new_content)

  run_cmd('git', 'add', SETUP_PY_PATH)
  run_cmd('git', 'commit', '-m',
          f'perfetto(python): Bump version to {new_version}')

  info(f"Version bump commit created on branch '{branch_name}'.")
  info("Please push this branch, create a pull request, and wait for it to "
       "be landed.")


def publish(commit: str) -> None:
  """Stage 2: Publishes the package and creates a commit to update the URL."""
  info(f"--- Stage 2: Publishing release for commit {commit} ---")

  original_branch = get_current_branch()
  info(f"Checking out commit {commit}...")
  run_cmd('git', 'checkout', commit)

  # Read the original content of setup.py at the release commit.
  content_at_commit = get_setup_py_content()
  new_version = get_current_version(content_at_commit)
  download_url = f"'https://github.com/google/perfetto/archive/{commit}.zip'"

  # Temporarily update download_url just for building the package.
  info(f"Temporarily setting download_url to {download_url}")
  temp_content = re.sub(r"download_url\s*=\s*'[^']*'",
                        f"download_url={download_url}", content_at_commit)
  write_setup_py_content(temp_content)

  try:
    info("Installing build dependencies into the virtual environment...")
    run_cmd(VENV_PYTHON, '-m', 'pip', 'install', 'build', 'twine')

    info("Building python package...")
    run_cmd(VENV_PYTHON, '-m', 'build', cwd='python')

    confirm("Ready to upload to PyPI. This is not reversible. Continue?")
    run_cmd(
        VENV_PYTHON,
        '-m',
        'twine',
        'upload',
        'dist/*',
        '--verbose',
        cwd='python')
    info("Successfully published to PyPI.")

  finally:
    # Always clean up and restore the repository to its original state.
    info("Cleaning up build artifacts...")
    shutil.rmtree('python/dist', ignore_errors=True)
    shutil.rmtree('python/perfetto.egg-info', ignore_errors=True)

    info(f"Restoring {SETUP_PY_PATH} to its state at commit {commit}...")
    write_setup_py_content(content_at_commit)

    info(f"Returning to original branch '{original_branch}'...")
    run_cmd('git', 'checkout', original_branch)

  # After successful publishing, create the final commit with the download_url.
  info("--- Creating final commit to update download_url ---")
  final_branch_name = prompt(
      "Enter a name for the final download_url update branch: ")
  run_cmd('git', 'checkout', '-b', final_branch_name)

  info(f"Updating download_url permanently in {SETUP_PY_PATH}...")
  final_content = get_setup_py_content()
  final_content = re.sub(r"download_url\s*=\s*'[^']*'",
                         f"download_url={download_url}", final_content)
  write_setup_py_content(final_content)

  run_cmd('git', 'add', SETUP_PY_PATH)
  run_cmd('git', 'commit', '-m',
          f'perfetto(python): Update download_url for v{new_version}')

  info(f"Commit for download_url created on branch '{final_branch_name}'.")
  info("Please push this branch and create a pull request to complete the "
       "release.")


def main() -> None:
  parser = argparse.ArgumentParser(
      description="Automates the Perfetto Python library release process.")
  parser.add_argument(
      '--bump-version',
      action='store_true',
      help="Stage 1: Bump version and create a release CL.")
  parser.add_argument(
      '--publish',
      action='store_true',
      help="Stage 2: Publish the release to PyPI.")
  parser.add_argument(
      '--commit',
      metavar='HASH',
      help="The landed commit hash of the version bump CL (for --publish).")

  args = parser.parse_args()

  # Ensure script is run from the repository root.
  if not os.path.exists(SETUP_PY_PATH):
    error(f"This script must be run from the root of the "
          f"perfetto repository.")

  # Ensure the virtual environment exists.
  if not os.path.exists(VENV_PYTHON):
    error(f"This script requires a virtual environment at '{VENV_PYTHON}'.")

  check_git_clean()

  if args.bump_version:
    if args.publish or args.commit:
      parser.error("--bump-version cannot be used with --publish or --commit.")
    bump_version()
  elif args.publish:
    if not args.commit:
      parser.error("--publish requires --commit.")
    publish(args.commit)
  else:
    parser.print_help()


if __name__ == '__main__':
  main()
