#!/usr/bin/env bash
# =============================================================================
# release.sh — disinto_release() function
#
# Handles vault TOML creation, branch setup on ops repo, PR creation,
# and auto-merge request for a versioned release.
#
# Globals expected:
#   FORGE_URL      - Forge instance URL (e.g. http://localhost:3000)
#   FORGE_TOKEN    - API token for Forge operations
#   FORGE_OPS_REPO - Ops repo slug (e.g. disinto-admin/myproject-ops)
#   FACTORY_ROOT   - Root of the disinto factory
#   PRIMARY_BRANCH - Primary branch name (e.g. main)
#
# Usage:
#   source "${FACTORY_ROOT}/lib/release.sh"
#   disinto_release <version>
# =============================================================================
set -euo pipefail

# Source action-vault.sh for _vault_log helper
source "${FACTORY_ROOT}/lib/action-vault.sh"

# Assert required globals are set before using this module.
_assert_release_globals() {
  local missing=()
  [ -z "${FORGE_URL:-}" ]      && missing+=("FORGE_URL")
  [ -z "${FORGE_TOKEN:-}" ]    && missing+=("FORGE_TOKEN")
  [ -z "${FORGE_OPS_REPO:-}" ] && missing+=("FORGE_OPS_REPO")
  [ -z "${FACTORY_ROOT:-}" ]   && missing+=("FACTORY_ROOT")
  [ -z "${PRIMARY_BRANCH:-}" ] && missing+=("PRIMARY_BRANCH")
  if [ "${#missing[@]}" -gt 0 ]; then
    echo "Error: release.sh requires these globals to be set: ${missing[*]}" >&2
    exit 1
  fi
}

disinto_release() {
  _assert_release_globals

  local version="${1:-}"
  local formula_path="${FACTORY_ROOT}/formulas/release.toml"

  if [ -z "$version" ]; then
    echo "Error: version required" >&2
    echo "Usage: disinto release <version>" >&2
    echo "Example: disinto release v1.2.0" >&2
    exit 1
  fi

  # Validate version format (must start with 'v' followed by semver)
  if ! echo "$version" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
    echo "Error: version must be in format v1.2.3 (semver with 'v' prefix)" >&2
    exit 1
  fi

  # Load project config to get FORGE_OPS_REPO
  if [ -z "${PROJECT_NAME:-}" ]; then
    # PROJECT_NAME is unset - detect project TOML from projects/ directory
    local found_toml
    found_toml=$(find "${FACTORY_ROOT}/projects" -maxdepth 1 -name "*.toml" ! -name "*.example" 2>/dev/null | head -1)
    if [ -n "$found_toml" ]; then
      source "${FACTORY_ROOT}/lib/load-project.sh" "$found_toml"
    fi
  else
    local project_toml="${FACTORY_ROOT}/projects/${PROJECT_NAME}.toml"
    if [ -f "$project_toml" ]; then
      source "${FACTORY_ROOT}/lib/load-project.sh" "$project_toml"
    fi
  fi

  # Check formula exists
  if [ ! -f "$formula_path" ]; then
    echo "Error: release formula not found at ${formula_path}" >&2
    exit 1
  fi

  # Get the ops repo root
  local ops_root="${FACTORY_ROOT}/../disinto-ops"
  if [ ! -d "${ops_root}/.git" ]; then
    echo "Error: ops repo not found at ${ops_root}" >&2
    echo "  Run 'disinto init' to set up the ops repo first" >&2
    exit 1
  fi

  # Generate a unique ID for the vault item
  local id="release-${version//./}"
  local vault_toml="${ops_root}/vault/actions/${id}.toml"

  # Create vault TOML with the specific version
  cat > "$vault_toml" <<EOF
# vault/actions/${id}.toml
# Release vault item for ${version}
# Auto-generated by disinto release

id = "${id}"
formula = "release"
context = "Release ${version}"
secrets = ["GITHUB_TOKEN", "CODEBERG_TOKEN"]
mounts = ["ssh"]
EOF

  echo "Created vault item: ${vault_toml}"

  # Create a PR to submit the vault item to the ops repo
  local branch_name="release/${version//./}"
  local pr_title="release: ${version}"
  local pr_body="Release ${version}

This PR creates a vault item for the release of version ${version}.

## Changes
- Added vault item: ${id}.toml

## Next Steps
1. Review this PR
2. Approve and merge
3. The vault runner will execute the release formula
"

  # Create branch from clean primary branch
  (
    cd "$ops_root"
    git checkout "$PRIMARY_BRANCH"
    git pull origin "$PRIMARY_BRANCH"
    git checkout -B "$branch_name" "$PRIMARY_BRANCH"

    # Add and commit only the vault TOML file
    git add "vault/actions/${id}.toml"
    git commit -m "$pr_title" -m "$pr_body" 2>/dev/null || true

    # Push branch
    git push -u origin "$branch_name" 2>/dev/null || {
      echo "Error: failed to push branch" >&2
      exit 1
    }
  )

  # Create PR
  local pr_response
  pr_response=$(curl -sf -X POST \
    -H "Authorization: token ${FORGE_TOKEN}" \
    -H "Content-Type: application/json" \
    "${FORGE_URL}/api/v1/repos/${FORGE_OPS_REPO}/pulls" \
    -d "{\"title\":\"${pr_title}\",\"head\":\"${branch_name}\",\"base\":\"${PRIMARY_BRANCH}\",\"body\":\"$(echo "$pr_body" | sed ':a;N;$!ba;s/\n/\\n/g')\"}" 2>/dev/null) || {
    echo "Error: failed to create PR" >&2
    echo "Response: ${pr_response}" >&2
    exit 1
  }

  local pr_number
  pr_number=$(echo "$pr_response" | jq -r '.number')

  local pr_url="${FORGE_URL}/${FORGE_OPS_REPO}/pulls/${pr_number}"

  # Enable auto-merge on the PR — Forgejo will auto-merge after approval
  _vault_log "Enabling auto-merge for PR #${pr_number}"
  curl -sf -X POST \
    -H "Authorization: token ${FORGE_TOKEN}" \
    -H "Content-Type: application/json" \
    "${FORGE_URL}/api/v1/repos/${FORGE_OPS_REPO}/pulls/${pr_number}/merge" \
    -d '{"Do":"merge","merge_when_checks_succeed":true}' >/dev/null 2>&1 || {
    echo "Warning: failed to enable auto-merge (may already be enabled or not supported)" >&2
  }

  echo ""
  echo "Release PR created: ${pr_url}"
  echo ""
  echo "Next steps:"
  echo "  1. Review the PR"
  echo "  2. Approve the PR (auto-merge will trigger after approval)"
  echo "  3. The vault runner will execute the release formula"
  echo ""
  echo "After merge, the release will:"
  echo "  1. Tag Forgejo main with ${version}"
  echo "  2. Push tag to mirrors (Codeberg, GitHub)"
  echo "  3. Build and tag the agents Docker image"
  echo "  4. Restart agent containers"
}
