#!/bin/bash

# ----------- Debug & Shell Strict Mode ----------- #
DEBUG=false  # doit être défini avant tout
for arg in "$@"; do [[ "$arg" == "--debug" ]] && DEBUG=true && break; done
$DEBUG && set -euo pipefail && trap 'echo "❌ Error on line $LINENO: command [$BASH_COMMAND]"' ERR

# ----------- Flags (Pre-init) ----------- #
FORCE_USER_CHECK=false
for arg in "$@"; do
  [[ "$arg" == "--force-user" ]] && FORCE_USER_CHECK=true && break
done

# ----------- User Check ----------- #
if [[ "${USER:-}" != "dbi" && "$FORCE_USER_CHECK" = false ]]; then
  echo "❌ This script must be run as user 'dbi'. Use --force-user to override."
  exit 1
fi

# ----------- Configuration ----------- #
GITEA_URL="https://git.inxs.me"
GITEA_USER="dbi"
CENTRAL_SERVER="dbi@ket.swallow-grue.ts.net"
REMOTE_TOKEN_PATH="/myshares/shared/home/dbi"
GIT_USER_NAME="Denis B"
GIT_USER_EMAIL="me@noxs.me"

SSH_KEY_PATH="$HOME/.ssh/id_ed25519_gitea"
SSH_CONFIG_PATH="$HOME/.ssh/config"
TOKEN_FILE="/tmp/.gitea_token"

# ----------- Flags ----------- #
DO_ADD_KEY=false
DO_ADD=false
DO_CLONE=false
DO_STATUS=false
DO_PULL=false
DO_PUSH=false
DO_SYNC=false
DO_DELETE=false
DO_LIST=false
DEBUG=false
AUTO_INIT=false
FORCE_OVERWRITE=false
PRIVATE=true
REPO_NAME=""
REPO_BASE_DIR=""
TARGET_DIR=""
LIST_FILTER=""

# ----------- Helpers ----------- #
error() { echo "❌ $*" >&2; exit 1; }
debug() { $DEBUG && echo "🐞 $*"; }

print_usage() {
  echo ""
  echo "Usage: gitea_setup.sh [--add-key]"
  echo "                      [--add|--clone|--status|--pull|--push|--sync|--delete(del/destroy/rm)|--list]" 
  echo "                            [--repo-name <name>]"
  echo "                            [--base-dir <path>|--target-dir <absolute path>]"
  echo "                      [--auto-init] [--private <true|false>] [--force-overwrite] [--debug] [--force-user]"
  echo "                      [--list]                         List user repositories"
  echo "                            [--filter <regex>]         Filter repo names (used with --list)"
  echo ""
  exit 1
}

[[ $# -eq 0 ]] && print_usage

# ----------- Parse Arguments ----------- #
while [[ $# -gt 0 ]]; do
  debug "Parsing arg: $1"
  case "$1" in
    --add-key) DO_ADD_KEY=true ;;
    --add) DO_ADD=true ;;
    --all) DO_ADD_KEY=true; DO_ADD=true ;;
    --clone) DO_CLONE=true ;;
    --status) DO_STATUS=true ;;
    --pull) DO_PULL=true ;;
    --push) DO_PUSH=true ;;
    --sync) DO_SYNC=true ;;
    --delete|--del|--remove|--rm|--destroy) DO_DELETE=true ;;
    --list) DO_LIST=true ;;
    --filter) LIST_FILTER="$2"; shift ;;
    --repo-name) REPO_NAME="$2"; shift ;;
    --base-dir) REPO_BASE_DIR="$2"; shift ;;
    --target-dir) TARGET_DIR="$2"; shift ;;
    --auto-init) AUTO_INIT=true ;;
    --private) PRIVATE="$2"; shift ;;
    --force-overwrite) FORCE_OVERWRITE=true ;;
    --debug) DEBUG=true ;;
    --force-user) ;; # Already handled
    *) error "Unknown option: $1" ;;
  esac
  shift
done

debug "Flags - clone: $DO_CLONE, repo: $REPO_NAME"

# ----------- Validation ----------- #
if ! $DO_LIST && { $DO_ADD || $DO_CLONE || $DO_STATUS || $DO_PULL || $DO_PUSH || $DO_SYNC || $DO_DELETE; } && [[ -z "$REPO_NAME" ]]; then
  error "--repo-name is required for the requested operation"
fi

# ----------- Directory Handling ----------- #
if [[ -n "$TARGET_DIR" ]]; then
  REPO_DIR="$TARGET_DIR"
elif [[ -n "$REPO_BASE_DIR" ]]; then
  REPO_DIR="$REPO_BASE_DIR"
  $DO_CLONE && REPO_DIR="$REPO_BASE_DIR/$REPO_NAME"
else
  REPO_DIR="$(pwd)"
  $DO_CLONE && REPO_DIR="$REPO_DIR/$REPO_NAME"
fi

# ----------- Token Fetch ----------- #
mkdir -p "$HOME/.ssh"
chmod 700 "$HOME/.ssh"
KNOWN_HOSTS="$HOME/.ssh/known_hosts"

if [[ "$(hostname -f)" =~ ^(ket\.inxs\.me|ket\.swallow-grue\.ts\.net)$ ]]; then
  cp "$REMOTE_TOKEN_PATH/.gitea_token" "$TOKEN_FILE" || error "Local token copy failed"
else
  if ! ssh-keygen -F ket.swallow-grue.ts.net > /dev/null; then
    echo "🔐 Adding ket.swallow-grue.ts.net to known_hosts..."
    ssh-keyscan -H ket.swallow-grue.ts.net >> "$KNOWN_HOSTS" 2>/dev/null || error "Failed to scan SSH key"
    chmod 644 "$KNOWN_HOSTS"
  fi
  scp "$CENTRAL_SERVER:$REMOTE_TOKEN_PATH/.gitea_token" "$TOKEN_FILE" || error "Remote token fetch failed"
fi

chmod 600 "$TOKEN_FILE"
TOKEN=$(<"$TOKEN_FILE")

# ----------- SSH Key Setup Function ----------- #
ensure_ssh_key() {
  echo "🔐 Ensuring SSH key and config are in place..."

  mkdir -p "$HOME/.ssh"
  chmod 700 "$HOME/.ssh"

  # Génère la clé si absente
  if [[ ! -f "$SSH_KEY_PATH" || ! -f "${SSH_KEY_PATH}.pub" ]]; then
    echo "⚠️  SSH key [$SSH_KEY_PATH(.pub)] not found."
    echo "🔁 Generating new SSH key — any previous registration on Gitea may be obsolete."
    echo "👉 You may want to clean up old keys in your Gitea account manually."
    ssh-keygen -t ed25519 -f "$SSH_KEY_PATH" -C "temp" -q -N ""
  fi

  # Copie le fichier de config SSH si absent
  if [[ ! -f "$SSH_CONFIG_PATH" ]]; then
    echo "🔧 Copying SSH config..."
    cp_or_scp_config() {
      if [[ "$(hostname -f)" =~ ^(ket\.inxs\.me|ket\.swallow-grue\.ts\.net)$ ]]; then
        cp "$REMOTE_TOKEN_PATH/config" "$SSH_CONFIG_PATH"
      else
        scp "$CENTRAL_SERVER:$REMOTE_TOKEN_PATH/config" "$SSH_CONFIG_PATH"
      fi
    }
    cp_or_scp_config || error "SSH config copy failed"
    chmod 600 "$SSH_CONFIG_PATH"
  fi

  # Ajout de gitea.inxs.me:2222 à known_hosts
  if ! ssh-keygen -F "[gitea.inxs.me]:2222" > /dev/null; then
    echo "🔐 Adding gitea.inxs.me:2222 to known_hosts..."
    ssh-keyscan -p 2222 -H gitea.inxs.me >> "$HOME/.ssh/known_hosts" 2>/dev/null || error "Failed to scan gitea.inxs.me:2222"
    chmod 644 "$HOME/.ssh/known_hosts"
  fi

  # Lire la clé publique
  KEY_PUB=$(<"${SSH_KEY_PATH}.pub")
  PUB_ONLY=$(awk '{print $1 " " $2}' <<< "$KEY_PUB")

  # Vérifie les clés existantes sur Gitea
  EXISTING_KEYS=$(curl -s -H "Authorization: token $TOKEN" "$GITEA_URL/api/v1/user/keys")
  EXISTING_TITLES=$(echo "$EXISTING_KEYS" | jq -r '.[].title')

  # Génère un titre unique
  BASE_LABEL="$GITEA_USER@$(hostname)"
  KEY_LABEL="$BASE_LABEL"
  i=1
  while echo "$EXISTING_TITLES" | grep -qx "$KEY_LABEL"; do
    KEY_LABEL="${BASE_LABEL}_$i"
    ((i++))
  done

  # Vérifie si la clé est déjà enregistrée
  if echo "$EXISTING_KEYS" | jq -r '.[].key' | grep -q "$PUB_ONLY"; then
    echo "✅ SSH key already registered on Gitea."
  else
    echo "🌟 Uploading SSH key to Gitea as '$KEY_LABEL'..."

    RESPONSE=$(curl -s -w "HTTP_STATUS:%{http_code}" -X POST "$GITEA_URL/api/v1/user/keys" \
      -H "Content-Type: application/json" \
      -H "Authorization: token $TOKEN" \
      -d "$(jq -n --arg title "$KEY_LABEL" --arg key "$KEY_PUB" '{title: $title, key: $key}')")

    BODY=$(sed -e 's/HTTP_STATUS:.*//' <<< "$RESPONSE")
    STATUS=$(sed -n 's/.*HTTP_STATUS://p' <<< "$RESPONSE")

    if [[ "$STATUS" != "201" ]]; then
      echo "❌ Failed to upload SSH key. HTTP $STATUS"
      echo "Response: $BODY"
      exit 1
    else
      echo "✅ SSH key '$KEY_LABEL' successfully uploaded to Gitea."
    fi
  fi
}

# ----------- Trigger auto-key setup if any git operation ----------- #
if $DO_CLONE || $DO_PULL || $DO_PUSH || $DO_SYNC || $DO_STATUS || $DO_ADD || $DO_DELETE; then
  ensure_ssh_key
fi

# ----------- LIST Repos ----------- #
if $DO_LIST; then
  echo "📚 Listing repositories for user '$GITEA_USER'..."
  curl -s -H "Authorization: token $TOKEN" "$GITEA_URL/api/v1/user/repos?limit=500" \
    | jq -r --arg filter "${LIST_FILTER:-.*}" \
      '.[] | select(.name | test($filter)) | "\(.name) — \(.html_url)"'
  shred -u "$TOKEN_FILE"
  exit 0
fi

# ----------- Git Operations ----------- #
if $DO_STATUS; then
  [[ ! -d "$REPO_DIR/.git" ]] && error "Not a git repository: $REPO_DIR"
  cd "$REPO_DIR" && git status && exit 0
fi

if $DO_PULL; then
  [[ ! -d "$REPO_DIR/.git" ]] && error "Not a git repository: $REPO_DIR"
  cd "$REPO_DIR" && git pull --rebase origin main || error "Pull failed"
  exit 0
fi

if $DO_PUSH; then
  [[ ! -d "$REPO_DIR/.git" ]] && error "Not a git repository: $REPO_DIR"
  cd "$REPO_DIR"
  git add . && git commit -m "Auto commit" || true
  git push origin main || error "Push failed"
  exit 0
fi

if $DO_SYNC; then
  [[ ! -d "$REPO_DIR/.git" ]] && error "Not a git repository: $REPO_DIR"
  cd "$REPO_DIR"
  git pull --rebase origin main || error "Pull failed"
  git add . && git commit -m "Auto sync" || true
  git push origin main || error "Push failed"
  exit 0
fi

if $DO_DELETE; then
  echo "⚠️  Confirm deletion of '$REPO_NAME' on Gitea"
  read -p "Type 'yes' to confirm: " CONFIRM
  [[ "$CONFIRM" != "yes" ]] && { echo "❌ Aborted by user."; exit 1; }

  echo "🗑️  Deleting '$REPO_NAME'..."
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
    -H "Authorization: token $TOKEN" \
    "$GITEA_URL/api/v1/repos/$GITEA_USER/$REPO_NAME")

  shred -u "$TOKEN_FILE"
  [[ "$STATUS" == "204" ]] && echo "✅ Deleted." || error "❌ HTTP $STATUS"
  exit 0
fi

# ----------- Manual SSH Key Add ----------- #
if $DO_ADD_KEY; then
  ensure_ssh_key
  exit 0
fi

# ----------- Repo Create ----------- #
if $DO_ADD; then
  echo "📦 Creating or verifying repository '$REPO_NAME'..."
  CHECK_URL="$GITEA_URL/api/v1/repos/$GITEA_USER/$REPO_NAME"
  HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $TOKEN" "$CHECK_URL")

  if [[ "$HTTP_CODE" != "200" ]]; then
    echo "🛠️ Creating repository on Gitea..."
    PAYLOAD=$(jq -n \
      --arg name "$REPO_NAME" \
      --argjson private "$PRIVATE" \
      --argjson auto_init "$AUTO_INIT" \
      '{name: $name, private: $private, auto_init: $auto_init}')

    RESPONSE=$(curl -s -w "HTTP_STATUS:%{http_code}" -X POST "$GITEA_URL/api/v1/user/repos" \
      -H "Authorization: token $TOKEN" \
      -H "Content-Type: application/json" \
      -d "$PAYLOAD")

    BODY=$(sed -e 's/HTTP_STATUS:.*//' <<< "$RESPONSE")
    STATUS=$(sed -n 's/.*HTTP_STATUS://p' <<< "$RESPONSE")

    [[ "$STATUS" == "201" ]] && echo "✅ Repository created on Gitea." || { echo "$BODY"; error "❌ HTTP $STATUS"; }
  else
    echo "✅ Repository already exists on Gitea."
  fi

  # Initialize local repo if not already present
  if [[ ! -d "$REPO_DIR/.git" ]]; then
    echo "🛠️ Initializing local Git repository at $REPO_DIR..."
    mkdir -p "$REPO_DIR"
    cd "$REPO_DIR"
    git init -b main
    git config user.name "$GIT_USER_NAME"
    git config user.email "$GIT_USER_EMAIL"

    if [[ ! -f README.md ]]; then
      echo "# $REPO_NAME" > README.md
    fi

    git add .
    git commit -m "Initial commit"
    git remote add origin "git@gitea.inxs.me:$GITEA_USER/$REPO_NAME.git"
    git push -u origin main
    echo "🚀 Initial push to Gitea completed."
  else
    echo "📂 Local repo already exists at $REPO_DIR — skipping init."
  fi
fi
# ----------- Repo Clone ----------- #
if $DO_CLONE; then
  echo "📅 Cloning repository into $REPO_DIR"
  [[ -e "$REPO_DIR" ]] && error "Target directory '$REPO_DIR' already exists."
  git clone "git@gitea.inxs.me:$GITEA_USER/$REPO_NAME.git" "$REPO_DIR"
  exit 0
fi

shred -u "$TOKEN_FILE"