#!/bin/sh
# naixi-install — iKuai app CLI installer
# Usage:
#   naixi-install <file.ipkg>          install + enable + start
#   naixi-install <file.ipkg> --no-enable   install without starting
#   naixi-install -u <name>            uninstall by name
#   naixi-install -l                   list installed apps
set -eu

PRG="naixi-install"
APPMARKET_DB="/etc/mnt/ikuai/appmarket.db"
DOCKER_DB="/etc/mnt/ikuai/docker.db"
IK_DIR="/usr/ikuai"

ACTION="install"
ENABLE=yes
QUIET=0
IPKG=""
UNINSTALL_NAME=""

for arg in "$@"; do
  case "$arg" in
    --enable)    ENABLE=yes ;;
    --no-enable) ENABLE=no ;;
    -q|--quiet)  QUIET=1 ;;
    -u|--uninstall) ACTION="uninstall" ;;
    -l|--list)   ACTION="list" ;;
    -h|--help)
      cat <<EOF
Usage:
  $PRG <file.ipkg>              Install and start
  $PRG <file.ipkg> --no-enable  Install without starting
  $PRG -u <name>                Uninstall by app name
  $PRG -l                       List installed apps
EOF
      exit 0 ;;
    -*) echo "Unknown option: $arg" >&2; exit 1 ;;
    *)
      if [ "$ACTION" = "uninstall" ]; then
        UNINSTALL_NAME="$arg"
      else
        IPKG="$arg"
      fi ;;
  esac
done

log() { [ "$QUIET" = "0" ] && echo "[$PRG] $*"; }
err() { echo "[$PRG] ERROR: $*" >&2; exit 1; }

# ─── list ─────────────────────────────────────────────────────────
if [ "$ACTION" = "list" ]; then
  sqlite3 -header -column "$APPMARKET_DB" \
    "SELECT name, current_version, type, enabled, appid FROM applist ORDER BY name" 2>/dev/null \
    || echo "no apps installed"
  exit 0
fi

# ─── uninstall ────────────────────────────────────────────────────
if [ "$ACTION" = "uninstall" ]; then
  [ -n "$UNINSTALL_NAME" ] || err "uninstall requires a name: $PRG -u <name>"
  APP_PATH=$(sqlite3 "$APPMARKET_DB" "SELECT '/etc/disk_user/'||install_path||'/apps/'||name FROM applist WHERE name='$UNINSTALL_NAME'" 2>/dev/null)
  [ -n "$APP_PATH" ] || err "app not found: $UNINSTALL_NAME"

  log "uninstalling $UNINSTALL_NAME..."

  # Stop first
  SCRIPTS_DIR="$APP_PATH/.pkg/scripts"
  if [ -d "$SCRIPTS_DIR" ]; then
    cd "$SCRIPTS_DIR"
    [ -x "./PRE_UNINST.sh" ] && ./PRE_UNINST.sh >/dev/null 2>&1 || true
    [ -x "./stop.sh" ] && ./stop.sh >> "$APP_PATH/log/run.log" 2>&1 || true
    [ -x "./POST_UNINST.sh" ] && ./POST_UNINST.sh >/dev/null 2>&1 || true
  fi

  # Remove from db
  sqlite3 "$APPMARKET_DB" "DELETE FROM applist WHERE name='$UNINSTALL_NAME'" 2>/dev/null || true

  # Remove files (preserve .backup if exists)
  rm -rf "$APP_PATH" "/var/appmarket/$UNINSTALL_NAME" "$IK_DIR/www/static/appmarket/$UNINSTALL_NAME"

  log "done: $UNINSTALL_NAME removed"
  exit 0
fi

# ═══ install ══════════════════════════════════════════════════════
[ -n "$IPKG" ] || err "no package specified: $PRG <file.ipkg>"
[ -f "$IPKG" ] || err "file not found: $IPKG"

# ─── Find install disk ────────────────────────────────────────────
WORKDISK=$(sqlite3 "$DOCKER_DB" "select workdisk from global" 2>/dev/null) || err "cannot read docker.db"
[ -n "$WORKDISK" ] || err "no workdisk found"

ROOT_PATH="/etc/disk_user"
APPS_DIR="$ROOT_PATH/$WORKDISK/apps"
APPMARKET_DIR="/var/appmarket"
MAX_APPID_FILE="/etc/mnt/ikuai/appmarket/.max_appid"

log "disk=$WORKDISK"

# ─── Extract ──────────────────────────────────────────────────────
TMP=$(mktemp -d 2>/dev/null)
[ -z "$TMP" ] && TMP="/tmp/naixi-$$" && mkdir -p "$TMP"
trap 'rm -rf "$TMP"' EXIT

log "extracting $IPKG..."
tar xzf "$IPKG" -C "$TMP" 2>/dev/null || err "extraction failed"

PKG_NAME=$(ls "$TMP")
[ -d "$TMP/$PKG_NAME" ] || err "bad package structure"
SRC="$TMP/$PKG_NAME"
MANIFEST="$SRC/manifest.json"
[ -f "$MANIFEST" ] || err "manifest.json not found"

# ─── Parse manifest (awk fallback when no jq) ─────────────────────
json_str() { awk -F'"' "/\"$1\"/{print \$4; exit}" "$MANIFEST"; }

VERSION=$(json_str version)
DISPLAY_NAME=$(json_str display_name)
[ -z "$DISPLAY_NAME" ] && DISPLAY_NAME=$(json_str name)
DESCRIPTION=$(json_str description)
TYPE=$(json_str type)
[ -z "$TYPE" ] && TYPE=0
MAINTAINER=$(json_str maintainer)
MAINTAINER_URL=$(json_str maintainer_url)
DISTRIBUTOR=$(json_str distributor)
DISTRIBUTOR_URL=$(json_str distributor_url)

log "name=$PKG_NAME version=$VERSION type=$TYPE ($DISPLAY_NAME)"

# ─── Allocate appid ───────────────────────────────────────────────
cur=100000
[ -f "$MAX_APPID_FILE" ] && cur=$(cat "$MAX_APPID_FILE" 2>/dev/null || echo 100000)
dbmax=$(sqlite3 "$APPMARKET_DB" "select max(appid) from applist" 2>/dev/null || echo 0)
[ "$dbmax" -gt "$cur" ] 2>/dev/null && cur=$dbmax
APPID=$((cur + 1))
echo "$APPID" > "$MAX_APPID_FILE" 2>/dev/null || true
log "appid=$APPID"

# ─── Install ──────────────────────────────────────────────────────
APP_PATH="$APPS_DIR/$PKG_NAME"
log "installing to $APP_PATH..."

# Stop existing if upgrading
if [ -x "$APP_PATH/.pkg/scripts/stop.sh" ]; then
  cd "$APP_PATH/.pkg/scripts"
  ./stop.sh >> "$APP_PATH/log/run.log" 2>&1 2>/dev/null || true
  cd /
fi

mkdir -p "$APP_PATH/.pkg" "$APP_PATH/log" "$APP_PATH/.tmp" "$APP_PATH/.backup"
cp -rf "$SRC/"* "$APP_PATH/.pkg/" 2>/dev/null || err "copy failed"

# Symlinks (config/data/cache → .pkg/app/*)
if [ -d "$APP_PATH/.pkg/app/config" ]; then
  ln -sf .pkg/app/config "$APP_PATH/config"
  touch "$APP_PATH/config/environment"
  [ ! -e "$APP_PATH/.pkg/app/environment" ] && touch "$APP_PATH/.pkg/app/environment"
fi
[ -d "$APP_PATH/.pkg/app/data" ] && ln -sf .pkg/app/data "$APP_PATH/data"
[ -d "$APP_PATH/.pkg/app/cache" ] && ln -sf .pkg/app/cache "$APP_PATH/cache"

# Appmarket symlink + icons
mkdir -p "$APPMARKET_DIR"
[ ! -e "$APPMARKET_DIR/$PKG_NAME" ] && ln -s "$APP_PATH" "$APPMARKET_DIR/$PKG_NAME"

if [ -e "$APP_PATH/.pkg/ui/ico/app.png" ]; then
  mkdir -p "$IK_DIR/www/static/appmarket/$PKG_NAME/ico"
  cp -f "$APP_PATH/.pkg/ui/ico/app.png" "$IK_DIR/www/static/appmarket/$PKG_NAME/ico/"
fi
if [ -d "$APP_PATH/.pkg/ui/images" ]; then
  mkdir -p "$IK_DIR/www/static/appmarket/$PKG_NAME/images"
  cp -rf "$APP_PATH/.pkg/ui/images/"* "$IK_DIR/www/static/appmarket/$PKG_NAME/images/" 2>/dev/null || true
fi

# ─── Register in appmarket.db ─────────────────────────────────────
TIMESTAMP=$(date +%s)
DESC_B64=$(printf '%s' "$DESCRIPTION" | base64 | tr -d '\n')
README=""
[ -e "$APP_PATH/.pkg/readme" ] && README=$(cat "$APP_PATH/.pkg/readme" | base64 | tr -d '\n')
CHANGELOG=""
[ -e "$APP_PATH/.pkg/changelog" ] && CHANGELOG=$(cat "$APP_PATH/.pkg/changelog" | base64 | tr -d '\n')

sqlite3 "$APPMARKET_DB" "DELETE FROM applist WHERE name='$PKG_NAME'" 2>/dev/null || true
sqlite3 "$APPMARKET_DB" "INSERT INTO applist (
  enabled,name,appid,timestamp,display_name,location,ico,type,size,
  restart,current_version,maintainer,maintainer_url,distributor,distributor_url,
  origin,update_time,install_path,category,sub_category,desc,readme,changelog
) VALUES (
  '$ENABLE','$PKG_NAME',$APPID,$TIMESTAMP,'$DISPLAY_NAME','','',$TYPE,0,
  0,'$VERSION','$MAINTAINER','$MAINTAINER_URL','$DISTRIBUTOR','$DISTRIBUTOR_URL',
  3,$TIMESTAMP,'$WORKDISK',7,0,'$DESC_B64','$README','$CHANGELOG'
)" 2>/dev/null || err "failed to write appmarket.db"

log "registered (appid=$APPID)"

# ─── Lifecycle ────────────────────────────────────────────────────
SCRIPTS_DIR="$APP_PATH/.pkg/scripts"
if [ -d "$SCRIPTS_DIR" ]; then
  cd "$SCRIPTS_DIR"

  log "PRE_INST..."
  [ -x "./PRE_INST.sh" ] && ./PRE_INST.sh >/dev/null 2>&1 || true

  if [ "$ENABLE" = "yes" ]; then
    log "starting..."
    [ -x "./start.sh" ] && ./start.sh >> "$APP_PATH/log/run.log" 2>&1 || log "WARNING: start.sh failed (check log)"
  fi

  log "POST_INST..."
  [ -x "./POST_INST.sh" ] && ./POST_INST.sh >/dev/null 2>&1 || true
fi

echo "0" > "$APP_PATH/log/run.status"
log "done: $PKG_NAME v$VERSION (appid=$APPID)"
exit 0
