#!/usr/bin/env bash
# defapp.install.sh — backs up the current defapp folder as a zip, then
# converts it to the v2 standard skeleton (pilot for the new app standard).
#
# Usage:
#   defapp.install.sh -p websites/apps/defapp [-b /path/to/backups] [-d] [-y]
#   defapp.install.sh --path websites/apps/defapp [--backup-dir DIR] [--dry-run] [--yes]
#
# -p, --path         path to the defapp folder (required)
# -b, --backup-dir   where to write the backup zip (default: alongside --path)
# -d, --dry-run      print what would happen, change nothing
# -y, --yes          skip the confirmation prompt
# -h, --help         show this help
#
# What this does (safe, additive-first):
#   1. Zips the ENTIRE current defapp folder to a timestamped backup — this
#      happens before anything else, unconditionally, unless --dry-run.
#   2. Creates every new v2 mandatory folder that doesn't already exist
#      (mkdir -p — never deletes or overwrites existing folders/files).
#   3. Performs ONLY the moves that were explicitly decided and are
#      unambiguous:
#        - data/logs/*      -> data/tmp/logs/      (if data/logs exists)
#        - data/sql/*       -> sql/                (if data/sql exists; sql/
#                                                    stays top-level per decision)
#   4. Leaves everything else in place and prints a manual TODO list for
#      decisions that need a human, not a script:
#        - carving out public/ from wherever web-servable files currently live
#        - anything under var/ or a sessions/ folder, since sessions now
#          belong at system tier, not app tier — moving that requires
#          confirming no other app already depends on defapp's session path
#        - config/templates/ was rejected (config/ stays flat) — if it
#          exists, it's flagged, not auto-merged, in case it holds something
#          other than templates
#
# Nothing here touches src/ vs php/, docs/ structure, or extension folders
# (api/python/assets) — none of those needed a structural change per the
# decisions made.

set -euo pipefail

APP_PATH=""
BACKUP_DIR=""
DRY_RUN=0
ASSUME_YES=0

usage() {
  grep '^#' "$0" | sed 's/^# \{0,1\}//'
  exit 0
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    -p|--path) APP_PATH="$2"; shift 2 ;;
    -b|--backup-dir) BACKUP_DIR="$2"; shift 2 ;;
    -d|--dry-run) DRY_RUN=1; shift ;;
    -y|--yes) ASSUME_YES=1; shift ;;
    -h|--help) usage ;;
    *) echo "Unknown option: $1" >&2; usage ;;
  esac
done

if [[ -z "$APP_PATH" ]]; then
  echo "Error: -p/--path is required" >&2
  exit 1
fi

if [[ ! -d "$APP_PATH" ]]; then
  echo "Error: ${APP_PATH} does not exist or is not a directory" >&2
  exit 1
fi

APP_PATH="${APP_PATH%/}"
APP_NAME="$(basename "$APP_PATH")"
PARENT_DIR="$(dirname "$APP_PATH")"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"

if [[ -z "$BACKUP_DIR" ]]; then
  BACKUP_DIR="$PARENT_DIR"
fi

BACKUP_FILE="${BACKUP_DIR}/${APP_NAME}.backup.${TIMESTAMP}.zip"

echo "=== defapp v2 install ==="
echo "App path:    ${APP_PATH}"
echo "Backup file: ${BACKUP_FILE}"
echo "Dry run:     $([[ $DRY_RUN -eq 1 ]] && echo yes || echo no)"
echo

if [[ $ASSUME_YES -eq 0 && $DRY_RUN -eq 0 ]]; then
  read -r -p "Proceed with backup + restructure of '${APP_PATH}'? [y/N] " reply
  if [[ ! "$reply" =~ ^[Yy]$ ]]; then
    echo "Aborted."
    exit 0
  fi
fi

run() {
  if [[ $DRY_RUN -eq 1 ]]; then
    echo "  [dry-run] $*"
  else
    "$@"
  fi
}

# --- Step 1: backup (unconditional, before any structural change) ---
echo "Step 1: backing up ${APP_PATH} ..."
mkdir -p "$BACKUP_DIR"
if [[ $DRY_RUN -eq 1 ]]; then
  echo "  [dry-run] zip -r '${BACKUP_FILE}' '${APP_PATH}'"
else
  ( cd "$PARENT_DIR" && zip -r "$BACKUP_FILE" "$APP_NAME" -x '*/tmp/*' -x '*/.git/*' >/dev/null )
  echo "  backup written to ${BACKUP_FILE}"
fi

# --- Step 2: create every new v2 mandatory folder (additive only) ---
echo "Step 2: creating v2 mandatory folders (existing folders untouched) ..."
MANDATORY_DIRS=(
  "public"
  "admin"
  "pages"
  "templates"
  "config"
  "css/themes"
  "js"
  "img"
  "php"
  "data/config"
  "data/fonts"
  "data/tmp/logs"
  "docs"
  "ai/prompts"
  "ai/output"
  "audit"
  "tests"
  "scripts"
  "tools"
  "tmp"
)
for dir in "${MANDATORY_DIRS[@]}"; do
  target="${APP_PATH}/${dir}"
  if [[ -d "$target" ]]; then
    echo "  = ${dir}/ already exists"
  else
    run mkdir -p "$target"
    echo "  + created ${dir}/"
  fi
done

# --- Step 3: unambiguous decided moves only ---
echo "Step 3: applying decided moves ..."

if [[ -d "${APP_PATH}/data/logs" ]]; then
  run mkdir -p "${APP_PATH}/data/tmp/logs"
  run bash -c "shopt -s dotglob nullglob; mv '${APP_PATH}/data/logs/'* '${APP_PATH}/data/tmp/logs/' 2>/dev/null || true"
  echo "  moved data/logs/* -> data/tmp/logs/"
  if [[ $DRY_RUN -eq 0 ]] && [[ -z "$(ls -A "${APP_PATH}/data/logs" 2>/dev/null)" ]]; then
    run rmdir "${APP_PATH}/data/logs"
    echo "  removed now-empty data/logs/"
  fi
else
  echo "  (no data/logs/ found — skipped)"
fi

if [[ -d "${APP_PATH}/data/sql" ]]; then
  run mkdir -p "${APP_PATH}/sql"
  run bash -c "shopt -s dotglob nullglob; mv '${APP_PATH}/data/sql/'* '${APP_PATH}/sql/' 2>/dev/null || true"
  echo "  moved data/sql/* -> sql/ (top-level)"
  if [[ $DRY_RUN -eq 0 ]] && [[ -z "$(ls -A "${APP_PATH}/data/sql" 2>/dev/null)" ]]; then
    run rmdir "${APP_PATH}/data/sql"
    echo "  removed now-empty data/sql/"
  fi
else
  echo "  (no data/sql/ found — skipped)"
fi

# --- Step 4: flag decisions that need a human ---
echo
echo "=== Manual review needed ==="

if [[ ! -d "${APP_PATH}/public" || -z "$(ls -A "${APP_PATH}/public" 2>/dev/null)" ]]; then
  echo "  - public/ is empty: carve out the actual web-servable files from"
  echo "    wherever they currently live (likely pages/ or app root)."
fi

for candidate in "var" "var/sessions" "sessions"; do
  if [[ -d "${APP_PATH}/${candidate}" ]]; then
    echo "  - found ${candidate}/: sessions now belong at system tier"
    echo "    (system/data/tmp/sessions/), not app tier. Confirm no other"
    echo "    app depends on this path before moving it."
  fi
done

if [[ -d "${APP_PATH}/config/templates" ]]; then
  echo "  - found config/templates/: config/ was decided to stay flat."
  echo "    Check what's actually in here before merging — don't auto-move."
fi

echo
echo "Done. Nothing outside the mandatory-folder creation and the two"
echo "decided moves was changed automatically. Backup is at:"
echo "  ${BACKUP_FILE}"
