#!/usr/bin/env bash
# env.sh — Load environment and shared utilities
# Source this at the top of every script: source "$(dirname "$0")/lib/env.sh"

set -euo pipefail

# Resolve script root (parent of lib/)
FACTORY_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

# Container detection: when running inside the agent container, DISINTO_CONTAINER
# is set by docker-compose.yml.  Adjust paths so phase files, logs, and thread
# maps land on the persistent volume instead of /tmp (which is ephemeral).
if [ "${DISINTO_CONTAINER:-}" = "1" ]; then
  DISINTO_DATA_DIR="${HOME}/data"
  DISINTO_LOG_DIR="${DISINTO_DATA_DIR}/logs"
  mkdir -p "${DISINTO_DATA_DIR}" "${DISINTO_LOG_DIR}"/{dev,action,review,supervisor,vault,site,metrics}
else
  DISINTO_LOG_DIR="${FACTORY_ROOT}"
fi
export DISINTO_LOG_DIR

# Load secrets: prefer .env.enc (SOPS-encrypted), fall back to plaintext .env.
# Always source .env — cron jobs inside the container do NOT inherit compose
# env vars (FORGE_TOKEN, etc.). Compose-injected vars (like FORGE_URL) are
# already set and won't be clobbered since env.sh uses ${VAR:-default} patterns
# for derived values. FORGE_URL from .env (localhost:3000) is overridden below
# by the compose-injected value when running via docker exec.
if [ -f "$FACTORY_ROOT/.env.enc" ] && command -v sops &>/dev/null; then
  set -a
  _saved_forge_url="${FORGE_URL:-}"
  eval "$(sops -d --output-type dotenv "$FACTORY_ROOT/.env.enc" 2>/dev/null)" \
    || echo "Warning: failed to decrypt .env.enc — secrets not loaded" >&2
  set +a
  [ -n "$_saved_forge_url" ] && export FORGE_URL="$_saved_forge_url"
elif [ -f "$FACTORY_ROOT/.env" ]; then
  # Preserve compose-injected FORGE_URL (localhost in .env != forgejo in Docker)
  _saved_forge_url="${FORGE_URL:-}"
  set -a
  # shellcheck source=/dev/null
  source "$FACTORY_ROOT/.env"
  set +a
  [ -n "$_saved_forge_url" ] && export FORGE_URL="$_saved_forge_url"
fi

# PATH: foundry, node, system
export PATH="${HOME}/.local/bin:${HOME}/.foundry/bin:${HOME}/.nvm/versions/node/v22.20.0/bin:/usr/local/bin:/usr/bin:/bin:${PATH}"
export HOME="${HOME:-/home/debian}"

# Load project TOML if PROJECT_TOML is set (by poll scripts that accept project arg)
if [ -n "${PROJECT_TOML:-}" ] && [ -f "$PROJECT_TOML" ]; then
  source "${FACTORY_ROOT}/lib/load-project.sh" "$PROJECT_TOML"
fi

# Forge token: new FORGE_TOKEN > legacy CODEBERG_TOKEN
if [ -z "${FORGE_TOKEN:-}" ]; then
  FORGE_TOKEN="${CODEBERG_TOKEN:-}"
fi
export FORGE_TOKEN
export CODEBERG_TOKEN="${FORGE_TOKEN}"  # backwards compat

# Review bot token: FORGE_REVIEW_TOKEN > legacy REVIEW_BOT_TOKEN
export FORGE_REVIEW_TOKEN="${FORGE_REVIEW_TOKEN:-${REVIEW_BOT_TOKEN:-}}"
export REVIEW_BOT_TOKEN="${FORGE_REVIEW_TOKEN}"  # backwards compat

# Per-agent tokens (#747): each agent gets its own Forgejo identity.
# Falls back to FORGE_TOKEN for backwards compat with single-token setups.
export FORGE_PLANNER_TOKEN="${FORGE_PLANNER_TOKEN:-${FORGE_TOKEN}}"
export FORGE_GARDENER_TOKEN="${FORGE_GARDENER_TOKEN:-${FORGE_TOKEN}}"
export FORGE_VAULT_TOKEN="${FORGE_VAULT_TOKEN:-${FORGE_TOKEN}}"
export FORGE_SUPERVISOR_TOKEN="${FORGE_SUPERVISOR_TOKEN:-${FORGE_TOKEN}}"
export FORGE_PREDICTOR_TOKEN="${FORGE_PREDICTOR_TOKEN:-${FORGE_TOKEN}}"
export FORGE_ACTION_TOKEN="${FORGE_ACTION_TOKEN:-${FORGE_TOKEN}}"

# Bot usernames filter: FORGE_BOT_USERNAMES > legacy CODEBERG_BOT_USERNAMES
export FORGE_BOT_USERNAMES="${FORGE_BOT_USERNAMES:-${CODEBERG_BOT_USERNAMES:-dev-bot,review-bot,planner-bot,gardener-bot,vault-bot,supervisor-bot,predictor-bot,action-bot}}"
export CODEBERG_BOT_USERNAMES="${FORGE_BOT_USERNAMES}"  # backwards compat

# Project config (FORGE_* preferred, CODEBERG_* fallback)
export FORGE_REPO="${FORGE_REPO:-${CODEBERG_REPO:-}}"
export CODEBERG_REPO="${FORGE_REPO}"  # backwards compat
export FORGE_URL="${FORGE_URL:-http://localhost:3000}"
export FORGE_API="${FORGE_API:-${FORGE_URL}/api/v1/repos/${FORGE_REPO}}"
export FORGE_WEB="${FORGE_WEB:-${FORGE_URL}/${FORGE_REPO}}"
export CODEBERG_API="${FORGE_API}"  # backwards compat
export CODEBERG_WEB="${FORGE_WEB}"  # backwards compat
# tea CLI login name: derived from FORGE_URL (codeberg vs local forgejo)
if [ -z "${TEA_LOGIN:-}" ]; then
  case "${FORGE_URL}" in
    *codeberg.org*) TEA_LOGIN="codeberg" ;;
    *)              TEA_LOGIN="forgejo" ;;
  esac
fi
export TEA_LOGIN

export PROJECT_NAME="${PROJECT_NAME:-${FORGE_REPO##*/}}"
export PROJECT_REPO_ROOT="${PROJECT_REPO_ROOT:-/home/${USER}/${PROJECT_NAME}}"
export PRIMARY_BRANCH="${PRIMARY_BRANCH:-master}"

# Ops repo: operational data (vault items, journals, evidence, prerequisites).
# Default convention: sibling directory named {project}-ops.
export OPS_REPO_ROOT="${OPS_REPO_ROOT:-/home/${USER}/${PROJECT_NAME}-ops}"

# Forge repo slug for the ops repo (used by agents that commit to ops).
export FORGE_OPS_REPO="${FORGE_OPS_REPO:-${FORGE_REPO:+${FORGE_REPO}-ops}}"
export WOODPECKER_REPO_ID="${WOODPECKER_REPO_ID:-}"
export WOODPECKER_SERVER="${WOODPECKER_SERVER:-http://localhost:8000}"
export CLAUDE_TIMEOUT="${CLAUDE_TIMEOUT:-7200}"

# Vault-only token guard (#745): external-action tokens (GITHUB_TOKEN, CLAWHUB_TOKEN)
# must NEVER be available to agents. They live in .env.vault.enc and are injected
# only into the ephemeral vault-runner container at fire time. Unset them here so
# even an accidental .env inclusion cannot leak them into agent sessions.
unset GITHUB_TOKEN 2>/dev/null || true
unset CLAWHUB_TOKEN 2>/dev/null || true

# Disable Claude Code auto-updater, telemetry, error reporting in factory sessions.
# Factory processes must never phone home or auto-update mid-session (#725).
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1

# Shared log helper
log() {
  printf '[%s] %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')" "$*"
}

# Forge API helper — usage: forge_api GET /issues?state=open
forge_api() {
  local method="$1" path="$2"
  shift 2
  curl -sf -X "$method" \
    -H "Authorization: token ${FORGE_TOKEN}" \
    -H "Content-Type: application/json" \
    "${FORGE_API}${path}" "$@"
}
# Backwards-compat alias
codeberg_api() { forge_api "$@"; }

# Paginate a Forge API GET endpoint and return all items as a merged JSON array.
# Usage: forge_api_all /path             (no existing query params)
#        forge_api_all /path?a=b         (with existing params — appends &limit=50&page=N)
#        forge_api_all /path TOKEN       (optional second arg: token; defaults to $FORGE_TOKEN)
forge_api_all() {
  local path_prefix="$1"
  local FORGE_TOKEN="${2:-${FORGE_TOKEN}}"
  local sep page page_items count all_items="[]"
  case "$path_prefix" in
    *"?"*) sep="&" ;;
    *) sep="?" ;;
  esac
  page=1
  while true; do
    page_items=$(forge_api GET "${path_prefix}${sep}limit=50&page=${page}")
    count=$(printf '%s' "$page_items" | jq 'length')
    [ "$count" -eq 0 ] && break
    all_items=$(printf '%s\n%s' "$all_items" "$page_items" | jq -s 'add')
    [ "$count" -lt 50 ] && break
    page=$((page + 1))
  done
  printf '%s' "$all_items"
}
# Backwards-compat alias
codeberg_api_all() { forge_api_all "$@"; }

# Woodpecker API helper
woodpecker_api() {
  local path="$1"
  shift
  curl -sfL \
    -H "Authorization: Bearer ${WOODPECKER_TOKEN}" \
    "${WOODPECKER_SERVER}/api${path}" "$@"
}

# Woodpecker DB query helper
wpdb() {
  PGPASSWORD="${WOODPECKER_DB_PASSWORD}" psql \
    -U "${WOODPECKER_DB_USER:-woodpecker}" \
    -h "${WOODPECKER_DB_HOST:-127.0.0.1}" \
    -d "${WOODPECKER_DB_NAME:-woodpecker}" \
    -t "$@" 2>/dev/null
}

# Memory guard — exit 0 (skip) if available RAM is below MIN_MB.
# Usage: memory_guard [MIN_MB]   (default 2000)
memory_guard() {
  local min_mb="${1:-2000}"
  local avail_mb
  avail_mb=$(awk '/MemAvailable/{printf "%d", $2/1024}' /proc/meminfo)
  if [ "${avail_mb:-0}" -lt "$min_mb" ]; then
    log "SKIP: only ${avail_mb}MB available (need ${min_mb}MB)"
    exit 0
  fi
}

# Source tea helpers (available when tea binary is installed)
if command -v tea &>/dev/null; then
  # shellcheck source=tea-helpers.sh
  source "$(dirname "${BASH_SOURCE[0]}")/tea-helpers.sh"
fi
