#!/usr/bin/env bash

setup_file() {
  load "$PWD/tests/integration/helpers/common"
  _common_setup
  _add_server
  _new_app
}

teardown_file() {
  _rm_server
  _reset_recipe
}

setup() {
  load "$PWD/tests/integration/helpers/common"
  _common_setup
  _set_git_author
}

teardown() {
  _reset_recipe
  _reset_tags
  if [[ -d "$ABRA_DIR/recipes/foobar" ]]; then
    run rm -rf "$ABRA_DIR/recipes/foobar"
    assert_success
  fi
  if [[ -d "$ABRA_DIR/origin-recipes/foobar.git" ]]; then
    run rm -rf "$ABRA_DIR/origin-recipes/foobar.git"
    assert_success
  fi
}

@test "validate recipe argument" {
  run $ABRA recipe release --no-input
  assert_failure

  run $ABRA recipe release DOESNTEXIST --no-input
  assert_failure
}

@test "release patch bump" {
  run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch --commit
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" show
  assert_success
  assert_output --partial 'image: nginx:1.21.6'

  # NOTE(d1): ensure the latest tag is the one we expect
  _remove_tags
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag \
    -a "0.3.0+1.21.0" -m "fake: 0.3.0+1.21.0"
  assert_success

  run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
  assert_success
  assert_output --partial 'INFO new release published:'

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag --list
  assert_success
  assert_output --partial '0.3.1+1.21.6'
}

@test "release minor bump" {
  # NOTE(d1): ensure the latest tag is the one we expect
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout 0.3.0+1.21.0
  _remove_tags
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag \
    -a "0.3.0+1.21.0" -m "fake: 0.3.0+1.21.0"
  assert_success

  run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --minor --commit
  assert_success

  run $ABRA recipe release "$TEST_RECIPE" --no-input --minor
  assert_success
  assert_output --partial 'INFO new release published:'

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag --list
  assert_success
  assert_output --regexp '0\.4\.0\+1\.(.*)'
}

@test "release with unstaged changes" {
  run bash -c 'echo "# unstaged changes" >> "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"'
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" diff --quiet
  assert_failure

  run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
  assert_failure
  assert_output --partial "working directory not clean"
}

@test "release with staged changes" {
  run bash -c 'echo "# staged changes" >> "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"'
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" add compose.yml
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" diff --quiet --cached
  assert_failure

  run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
  assert_failure
  assert_output --partial "working directory not clean"
}

@test "release with next release note" {
  _mkfile "$ABRA_DIR/recipes/$TEST_RECIPE/release/next" "those are some release notes for the next release"

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout main
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" add release/next
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" commit -m "added some release notes"
  assert_success

  run $ABRA recipe release "$TEST_RECIPE" --no-input --minor
  assert_success
  assert_output --partial 'new release published:'

  assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE/release/next"
  assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/release/0.4.0+1.21.0"
  assert_file_contains "$ABRA_DIR/recipes/$TEST_RECIPE/release/0.4.0+1.21.0" "those are some release notes for the next release"
}

@test "recipe release conflict fails" {
  tagHash=$(_get_tag_hash "0.2.0+1.21.0")
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout "$tagHash"
  assert_success

  run sed -i "s/nginx:1.21.0/nginx:1.29.1/g" "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" diff
  assert_success
  assert_output --regexp 'nginx:1.29.1'

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" commit -am "updated nginx"
  assert_success

  run $ABRA recipe release "$TEST_RECIPE" --no-input "0.2.0+1.29.1"
  assert_failure
  assert_output --partial '0.2.0+... conflicts with a previous release: 0.2.0+1.21.0'
}

@test "error if recipe release --no-input and no initial version" {
  _remove_tags

  run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
  assert_failure
  assert_output --partial 'unable to continue'
  assert_output --partial 'initial version'
}

@test "recipe release without input fails with prompt" {
  run $ABRA recipe new foobar
  assert_success
  assert_exists "$ABRA_DIR/recipes/foobar"

  run $ABRA recipe release foobar --no-input --patch
  assert_failure
  assert_output --partial "input required for initial version"
}

@test "release new recipe: fail without input" {
  run $ABRA recipe new foobar
  assert_success
  assert_exists "$ABRA_DIR/recipes/foobar"

  run bash -c "$ABRA recipe release foobar --no-input"
  assert_failure
  assert_output --partial 'unable to continue, input required for initial version'
}

# note: piping 0.1.0 from stdin is not testable right now because release notes also wants input
# survey lib used for prompts breaks multi-line stdin for multi-prompt
@test "release new recipe: development release" {
  run $ABRA recipe new foobar
  assert_success
  assert_exists "$ABRA_DIR/recipes/foobar"

  # fake origin
  git clone "$ABRA_DIR/recipes/foobar" "$ABRA_DIR/origin-recipes/foobar.git" --bare
  assert_success

  run git -C "$ABRA_DIR/recipes/foobar" remote add origin-ssh "$ABRA_DIR/origin-recipes/foobar.git"
  assert_success

  run bash -c "$ABRA recipe release foobar 0.1.0+1.2.0 --no-input"
  assert_success
  assert_output --regexp 'coop-cloud\.\$\{STACK_NAME\}\.version=0\.1\.0\+1\.2.*'
}

@test "release newly created recipe with no version label" {
  run $ABRA recipe new foobar
  assert_success
  assert_exists "$ABRA_DIR/recipes/foobar"

  run sed -i 's/- "coop-cloud.${STACK_NAME}.version="/#- "coop-cloud.${STACK_NAME}.version="/g' \
    "$ABRA_DIR/recipes/foobar/compose.yml"
  assert_success

  run git -C "$ABRA_DIR/recipes/foobar" commit -am "updated nginx"
  assert_success

  run bash -c "echo 0.1.0 | $ABRA recipe release foobar --patch"
  assert_failure
  assert_output --partial "automagic insertion not supported yet"
}

@test "push during release fails" {
  tagHash=$(_get_tag_hash "0.2.0+1.21.0")
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout "$tagHash"
  assert_success

  run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch --commit
  assert_success

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" show
  assert_success
  assert_output --partial 'image: nginx:1.21.6'

  wantHash="$(_get_current_hash)"

  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" remote set-url origin-ssh "$ABRA_DIR/does/not/exist"
  assert_success

  run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
  assert_failure
  assert_output --partial 'failed to publish new release:'
  assert_output --partial 'any changes made have been reverted'

  assert_equal "$wantHash" "$(_get_current_hash)"

  assert_equal "$(_git_status)" ""
}

@test "release, fail, release: works" {
  tagHash=$(_get_tag_hash "0.2.0+1.21.0")
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout "$tagHash"
  assert_success

  run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch --commit
  assert_success

  # NOTE(d1): fake broken remote so the release fails
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" remote set-url origin-ssh "$ABRA_DIR/does/not/exist"
  assert_success

  run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
  assert_failure

  # NOTE(d1): correct remote so release can proceed
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" remote set-url origin-ssh "$ABRA_DIR/origin-recipes/$TEST_RECIPE.git"
  assert_success

  run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
  assert_success
}
