#!/bin/ash
# Shared /etc/gitea/app.ini helpers for ash/bash (Alpine BE).
# shellcheck shell=sh

gitea_ini_file="${GITEA_INI:-/etc/gitea/app.ini}"

# ini_get FILE SECTION KEY  -> prints value (last PATH wins without section; use section)
ini_get() {
  _ini_file="$1"
  _ini_section="$2"
  _ini_key="$3"
  awk -F= -v sec="[$_ini_section]" -v key="$_ini_key" '
    function trim(s) {
      sub(/^[ \t\r\n]+/, "", s)
      sub(/[ \t\r\n]+$/, "", s)
      return s
    }
    function unquote(s) {
      s = trim(s)
      if (s ~ /^".*"$/) { sub(/^"/, "", s); sub(/"$/, "", s) }
      if (s ~ /^'\''.*'\''$/) { sub(/^'\''/, "", s); sub(/'\''$/, "", s) }
      return s
    }
    /^[ \t]*#/ { next }
    /^[ \t]*;/ { next }
    /^\[/ {
      cur = $0
      gsub(/^\[|\]$/, "", cur)
      cur = trim(cur)
      cur = tolower(cur)
      next
    }
    {
      k = trim($1)
      if (k != key) next
      sec_l = tolower(sec)
      gsub(/^\[|\]$/, "", sec_l)
      if (sec != "" && cur != sec_l) next
      v = $0
      sub(/^[^=]*=/, "", v)
      print unquote(v)
      exit
    }
  ' "$_ini_file"
}

gitea_load_config() {
  gitea_ini_file="${GITEA_INI:-/etc/gitea/app.ini}"
  if [ ! -r "$gitea_ini_file" ]; then
    echo "ERROR: cannot read $gitea_ini_file (set GITEA_INI=...)" >&2
    return 1
  fi

  GITEA_APP_INI="$gitea_ini_file"
  _load_ini_keys() {
    _f="$1"
    GITEA_REPO_ROOT="$(ini_get "$_f" repository ROOT)"
    GITEA_APP_DATA="$(ini_get "$_f" server APP_DATA_PATH)"
    GITEA_ROOT_URL="$(ini_get "$_f" server ROOT_URL)"
    GITEA_HTTP_PORT="$(ini_get "$_f" server HTTP_PORT)"
    GITEA_DOMAIN="$(ini_get "$_f" server DOMAIN)"
    GITEA_DB_TYPE="$(ini_get "$_f" database DB_TYPE)"
    GITEA_DB_HOST="$(ini_get "$_f" database HOST)"
    GITEA_DB_NAME="$(ini_get "$_f" database NAME)"
    GITEA_DB_USER="$(ini_get "$_f" database USER)"
    GITEA_DB_PASS="$(ini_get "$_f" database PASSWD)"
    GITEA_DB_PATH="$(ini_get "$_f" database PATH)"
    GITEA_LFS_PATH="$(ini_get "$_f" lfs PATH)"
    GITEA_LOG_ROOT="$(ini_get "$_f" log ROOT_PATH)"
  }
  _load_ini_keys "$gitea_ini_file"

  [ -n "$GITEA_APP_DATA" ] || GITEA_APP_DATA="/var/lib/gitea"
  # Canonical config on Alpine is often under APP_DATA, not /etc stub.
  if [ -r "$GITEA_APP_DATA/custom/conf/app.ini" ]; then
    _load_ini_keys "$GITEA_APP_DATA/custom/conf/app.ini"
    GITEA_APP_INI="$GITEA_APP_DATA/custom/conf/app.ini"
  fi

  [ -n "$GITEA_REPO_ROOT" ] || GITEA_REPO_ROOT="$GITEA_APP_DATA/data/gitea-repositories"
  [ -n "$GITEA_HTTP_PORT" ] || GITEA_HTTP_PORT="3000"
  [ -n "$GITEA_DB_TYPE" ] || GITEA_DB_TYPE="sqlite3"
  [ -n "$GITEA_ROOT_URL" ] || GITEA_ROOT_URL="${GITEA_ROOT_URL_DEFAULT:-https://apps.f0xx.org/app/androidcast_project/git/}"

  GITEA_RUN_USER="$(ini_get "$GITEA_APP_INI" "" RUN_USER)"
  [ -n "$GITEA_RUN_USER" ] || GITEA_RUN_USER="gitea"

  export GITEA_APP_INI GITEA_REPO_ROOT GITEA_APP_DATA GITEA_ROOT_URL GITEA_HTTP_PORT
  export GITEA_DOMAIN GITEA_DB_TYPE GITEA_DB_HOST GITEA_DB_NAME GITEA_DB_USER GITEA_DB_PASS
  export GITEA_DB_PATH GITEA_LFS_PATH GITEA_LOG_ROOT GITEA_RUN_USER

  # External URL (ROOT_URL) includes nginx subpath; direct :3000 API/git do not.
  GITEA_HTTP_SUBPATH="${GITEA_HTTP_SUBPATH:-}"
  if [ -z "$GITEA_HTTP_SUBPATH" ] && [ -n "$GITEA_ROOT_URL" ]; then
    _p="${GITEA_ROOT_URL#*://}"
    _p="${_p#*/}"
    case "$_p" in
      */*) GITEA_HTTP_SUBPATH="/${_p%/}" ;;
    esac
  fi
  GITEA_LOCAL_API="${GITEA_LOCAL_API:-http://127.0.0.1:${GITEA_HTTP_PORT}/api/v1}"
  export GITEA_HTTP_SUBPATH GITEA_LOCAL_API
}

# Must be absolute, no .., and under allowed prefixes (Gitea-owned paths only).
gitea_path_is_safe_to_wipe() {
  _target="$1"
  case "$_target" in
    ""|/*..*|*../*) return 1 ;;
  esac
  case "$_target" in
    /var/lib/gitea/*|/var/lib/gitea) return 0 ;;
    /data/gitea/*|/data/gitea) return 0 ;;
  esac
  return 1
}

# Gitea admin CLI must run as RUN_USER from app.ini (Alpine package: user "gitea", not "git").
gitea_run_as_service_user() {
  _run="${GITEA_RUN_USER:-gitea}"
  _cur="$(gitea_current_user)"
  if [ "$_cur" = "$_run" ]; then
    sh -c "$*"
    return $?
  fi
  if id "$_run" >/dev/null 2>&1; then
    su -s /bin/sh "$_run" -c "$*"
    return $?
  fi
  if id git >/dev/null 2>&1; then
    su -s /bin/sh git -c "$*"
    return $?
  fi
  echo "ERROR: cannot run gitea as '$_run' (set RUN_USER in app.ini)" >&2
  return 1
}

gitea_cli() {
  if command -v gitea >/dev/null 2>&1; then
    gitea_run_as_service_user "gitea -c '$GITEA_APP_INI' $*"
  else
    echo "WARN: gitea binary not in PATH" >&2
    return 1
  fi
}

gitea_current_user() {
  whoami 2>/dev/null || id -un 2>/dev/null || echo unknown
}

# Caller must be root (to su) or already GITEA_RUN_USER.
gitea_ensure_cli_access() {
  _run="${GITEA_RUN_USER:-gitea}"
  _cur="$(gitea_current_user)"
  if [ "$_cur" = "$_run" ]; then
    return 0
  fi
  if [ "$(id -u 2>/dev/null || echo 1)" -eq 0 ]; then
    return 0
  fi
  if id "$_run" >/dev/null 2>&1 && su -s /bin/sh "$_run" -c "true" 2>/dev/null; then
    return 0
  fi
  echo "ERROR: Gitea admin CLI must run as OS user '$_run' (RUN_USER in app.ini)." >&2
  echo "       You are '$_cur'. Re-run with:" >&2
  echo "         sudo ./gitea_attach_remote.sh git://..." >&2
  echo "       Or:" >&2
  echo "         sudo -u $_run ./gitea_attach_remote.sh git://..." >&2
  return 1
}

gitea_db_list_usernames() {
  case "$(echo "$GITEA_DB_TYPE" | tr '[:upper:]' '[:lower:]')" in
    mysql)
      command -v mysql >/dev/null 2>&1 || return 1
      _sock="${GITEA_DB_HOST:-/run/mysqld/mysqld.sock}"
      case "$_sock" in
        /*) mysql -u"$GITEA_DB_USER" ${GITEA_DB_PASS:+-p"$GITEA_DB_PASS"} -S "$_sock" "$GITEA_DB_NAME" \
          -N -e "SELECT name FROM user ORDER BY id" 2>/dev/null ;;
        *) mysql -u"$GITEA_DB_USER" ${GITEA_DB_PASS:+-p"$GITEA_DB_PASS"} -h "$_sock" "$GITEA_DB_NAME" \
          -N -e "SELECT name FROM user ORDER BY id" 2>/dev/null ;;
      esac
      ;;
    sqlite3|sqlite)
      command -v sqlite3 >/dev/null 2>&1 || return 1
      _db="${GITEA_DB_PATH:-}"
      [ -n "$_db" ] || _db="$GITEA_APP_DATA/gitea.db"
      [ -r "$_db" ] || _db="/var/lib/gitea/db/gitea.db"
      [ -r "$_db" ] || return 1
      sqlite3 "$_db" "SELECT name FROM user ORDER BY id" 2>/dev/null
      ;;
    *)
      return 1
      ;;
  esac
}

gitea_db_pick_admin_username() {
  case "$(echo "$GITEA_DB_TYPE" | tr '[:upper:]' '[:lower:]')" in
    mysql)
      command -v mysql >/dev/null 2>&1 || return 1
      _sock="${GITEA_DB_HOST:-/run/mysqld/mysqld.sock}"
      case "$_sock" in
        /*) mysql -u"$GITEA_DB_USER" ${GITEA_DB_PASS:+-p"$GITEA_DB_PASS"} -S "$_sock" "$GITEA_DB_NAME" \
          -N -e "SELECT name FROM user WHERE is_admin=1 ORDER BY id LIMIT 1" 2>/dev/null ;;
        *) mysql -u"$GITEA_DB_USER" ${GITEA_DB_PASS:+-p"$GITEA_DB_PASS"} -h "$_sock" "$GITEA_DB_NAME" \
          -N -e "SELECT name FROM user WHERE is_admin=1 ORDER BY id LIMIT 1" 2>/dev/null ;;
      esac
      ;;
    sqlite3|sqlite)
      command -v sqlite3 >/dev/null 2>&1 || return 1
      _db="${GITEA_DB_PATH:-$GITEA_APP_DATA/gitea.db}"
      [ -r "$_db" ] || _db="/var/lib/gitea/db/gitea.db"
      [ -r "$_db" ] || return 1
      sqlite3 "$_db" "SELECT name FROM user WHERE is_admin=1 ORDER BY id LIMIT 1" 2>/dev/null
      ;;
    *)
      return 1
      ;;
  esac
}

# One username per line (CLI as RUN_USER, else DB).
gitea_list_usernames() {
  _cli=""
  _cli="$(gitea_cli "admin" "user" "list" 2>/dev/null)" || true
  if [ -n "$_cli" ]; then
    echo "$_cli" | awk 'NR > 1 && NF >= 2 { print $2 }'
    return 0
  fi
  gitea_db_list_usernames
}

gitea_user_exists() {
  _u="$1"
  gitea_list_usernames | grep -Fx "$_u" >/dev/null 2>&1
}

# First site-admin account, else first user.
gitea_pick_owner_username() {
  _pick=""
  _pick="$(gitea_cli "admin" "user" "list" 2>/dev/null \
    | awk 'NR > 1 && NF >= 2 && ($5 == "true" || $5 == "1") { print $2; exit }')"
  if [ -n "$_pick" ]; then
    printf '%s' "$_pick"
    return 0
  fi
  _pick="$(gitea_db_pick_admin_username)"
  if [ -n "$_pick" ]; then
    printf '%s' "$_pick"
    return 0
  fi
  gitea_list_usernames | head -n 1
}

