#!/usr/bin/env bash
set -euo pipefail
source "$SHELLOPS_DIR/.envrc"

:<<'DOC'
Computes the planned next version from PR labels and updates manifest.json.

Runs at PR time (CI step). Reads PR labels from environment, computes the
next version using the bump state machine, and updates latest/stable in the
manifest. Posts a PR comment on label conflicts.

Idempotent: skips the commit if latest is already at the computed version.
DOC

import \
  "$SHELLOPS_DIR/lib/bump.api.sh" \
  "$SHELLOPS_DIR/lib/forgejo.api.sh"

USAGE="$(cat <<EOF
Plans the next version from PR labels and updates manifest.json.

Usage: ops plan-version [-h,--help]

Environment:
  CI_COMMIT_PULL_REQUEST          Pull request number
  CI_COMMIT_PULL_REQUEST_LABELS   Comma-separated label names

  These are auto-detected from GitHub Actions event context if not
  already set.

EOF
)"

function main() {
  parse_args "$@"

  local labels
  labels="$(read_labels)"

  if [[ -z "$labels" ]]; then
    log "No labels found, skipping version planning."
    exit 0
  fi

  if ! validate_meta_labels "$labels"; then
    post_conflict_comment "$labels"
    exit 1
  fi

  local base_version manifest_latest next_version
  base_version="$(latest_version)"
  manifest_latest="$(manifest_get latest)"
  next_version="$(compute_next_version "$base_version" "$labels")" || exit 1

  if [[ "$next_version" == "$manifest_latest" ]]; then
    log "Version already planned at $manifest_latest, no update needed."
    exit 0
  fi

  update_manifest "$next_version"
  log "Planned version: $manifest_latest -> $next_version (base: $base_version)"
}

function read_labels() {
  if [[ -z "${CI_COMMIT_PULL_REQUEST_LABELS:-}" ]]; then
    try_auto_detect_labels
  fi

  echo "${CI_COMMIT_PULL_REQUEST_LABELS:-}"
}

function try_auto_detect_labels() {
  if [[ -z "${GITHUB_ACTIONS:-}" || -z "${GITHUB_EVENT_PATH:-}" ]]; then
    return
  fi

  log "Auto-detecting labels from GitHub Actions context..."
  CI_COMMIT_PULL_REQUEST="${CI_COMMIT_PULL_REQUEST:-$(jq -r '.pull_request.number' "$GITHUB_EVENT_PATH")}"
  CI_COMMIT_PULL_REQUEST_LABELS="$(jq -r '[.pull_request.labels[].name] | join(",")' "$GITHUB_EVENT_PATH")"
  export CI_COMMIT_PULL_REQUEST CI_COMMIT_PULL_REQUEST_LABELS
}

function update_manifest() {
  local next_version="$1"

  manifest_set latest "$next_version"

  if is_release_version "$next_version"; then
    manifest_set stable "$next_version"
  fi
}

function post_conflict_comment() {
  local labels="$1"

  if [[ -z "${CI_COMMIT_PULL_REQUEST:-}" || -z "${FORGEJO_PR_TOKEN:-}" ]]; then
    return
  fi

  local body
  body="$(format_conflict_message "$labels")"

  local options
  options="$(jq_set "{}" \
    '.issue_number' "$CI_COMMIT_PULL_REQUEST" \
    '.token' "$FORGEJO_PR_TOKEN")"

  forgejo_create_comment "$options" "$body" || log "Warning: failed to post conflict comment"
}

function format_conflict_message() {
  local labels="$1"

  cat <<MSG
**Version Planning Failed: Contradictory Labels**

This PR has multiple version-transition labels: \`${labels}\`

Only one of these is allowed per PR:
- \`meta/experimental\` — Start a prerelease dev series
- \`meta/promote\` — Graduate one channel up (dev→alpha→beta→rc→stable)
- \`meta/release\` — Promote any prerelease directly to stable

Please remove the conflicting labels and re-run CI.
MSG
}

function parse_args() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      -h|--help) log "$USAGE" && exit 0 ;;
      -*)
        log "Unknown option: $1"
        log "$USAGE"
        exit 1
        ;;
    esac
    shift
  done
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  main "$@"
fi
