#!/usr/bin/env bash
# Postwoo installer — plain PHP 8.3, no Composer.
#
#   bash install.sh                       # interactive
#   bash install.sh --app-url=https://postwoo.example.com --db=mysql --db-password=… \
#                   --admin-email=you@agency.com --admin-password=… --org="Your Agency" --yes
#   sudo bash install.sh --systemd --web-user=www-data …   # also installs the worker service + scheduler cron
#   bash install.sh --upgrade             # after pulling a new version: migrate + restart the worker
#
# Safe to re-run: existing .env values, APP_KEY, users and organizations are kept.
set -euo pipefail

APP_URL=""; DB_DRIVER=""; DB_HOST="127.0.0.1"; DB_PORT="3306"; DB_NAME="postwoo"; DB_USER="postwoo"; DB_PASS=""
ADMIN_EMAIL=""; ADMIN_NAME=""; ADMIN_PASS=""; ORG_NAME=""; WEB_USER=""; YES=0; DEMO=0; SYSTEMD=0; UPGRADE=0; ENV_NAME="production"
for arg in "$@"; do
  case "$arg" in
    --app-url=*) APP_URL="${arg#*=}";; --db=*) DB_DRIVER="${arg#*=}";; --db-host=*) DB_HOST="${arg#*=}";; --db-port=*) DB_PORT="${arg#*=}";;
    --db-name=*) DB_NAME="${arg#*=}";; --db-user=*) DB_USER="${arg#*=}";; --db-password=*) DB_PASS="${arg#*=}";;
    --admin-email=*) ADMIN_EMAIL="${arg#*=}";; --admin-name=*) ADMIN_NAME="${arg#*=}";; --admin-password=*) ADMIN_PASS="${arg#*=}";;
    --org=*) ORG_NAME="${arg#*=}";; --web-user=*) WEB_USER="${arg#*=}";; --env=*) ENV_NAME="${arg#*=}";;
    --yes|-y) YES=1;; --demo) DEMO=1;; --systemd) SYSTEMD=1;; --upgrade) UPGRADE=1;;
    --help|-h) sed -n 2,12p "$0"; exit 0;;
    *) echo "Unknown option: $arg" >&2; exit 2;;
  esac
done

cd "$(dirname "$0")"
ROOT="$(pwd)"
bold() { printf '\033[1m%s\033[0m\n' "$*"; }
ok()   { printf '  \033[32m✔\033[0m %s\n' "$*"; }
warn() { printf '  \033[33m!\033[0m %s\n' "$*"; }
die()  { printf '  \033[31m✘ %s\033[0m\n' "$*" >&2; exit 1; }
ask()  { # ask VAR "Prompt" "default" [secret]
  local var="$1" prompt="$2" def="${3:-}" secret="${4:-}" val
  if [ "$YES" = 1 ] || [ ! -t 0 ]; then printf -v "$var" '%s' "${!var:-$def}"; return; fi
  if [ -n "${!var:-}" ]; then return; fi
  if [ -n "$secret" ]; then read -r -s -p "  $prompt${def:+ [$def]}: " val; echo; else read -r -p "  $prompt${def:+ [$def]}: " val; fi
  printf -v "$var" '%s' "${val:-$def}"
}
set_env() { # set_env KEY VALUE  (replaces or appends in .env; keeps existing non-empty values unless FORCE=1)
  local key="$1" value="$2" current
  current="$(grep -E "^${key}=" .env | head -1 | cut -d= -f2- | sed 's/[[:space:]]*#.*$//' || true)"
  if [ -n "$current" ] && [ "${FORCE:-0}" != 1 ]; then return; fi
  local escaped; escaped="$(printf '%s' "$value" | sed -e 's/[\/&|]/\\&/g')"
  if grep -qE "^${key}=" .env; then sed -i -E "s|^${key}=.*|${key}=${escaped}|" .env; else printf '%s=%s\n' "$key" "$value" >> .env; fi
}

bold "Postwoo installer"
echo "  Directory: $ROOT"

# ── 1. Preflight ────────────────────────────────────────────────────────────
bold "1/6 Checking PHP"
command -v php >/dev/null || die "php not found. Install PHP 8.3 (e.g. apt install php8.3-cli php8.3-fpm php8.3-mysql php8.3-sqlite3 php8.3-gd php8.3-intl php8.3-mbstring php8.3-curl php8.3-xml)."
PHP_VERSION="$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')"
php -r 'exit(version_compare(PHP_VERSION, "8.3.0", ">=") ? 0 : 1);' || die "PHP 8.3 or newer is required (found $PHP_VERSION)."
ok "PHP $PHP_VERSION"
missing=""
for ext in pdo sodium mbstring curl json openssl gd intl ctype fileinfo; do php -m | grep -qi "^${ext}$" || missing="$missing $ext"; done
[ -z "$missing" ] || die "Missing PHP extensions:$missing"
ok "Required extensions present (pdo, sodium, mbstring, curl, json, openssl, gd, intl)"
php -m | grep -qi '^pcntl$' && ok "pcntl available (graceful worker shutdown, multi-process load test)" || warn "pcntl missing — workers still run; signals and publishing:loadtest --workers are disabled"
php -m | grep -qi '^redis$' && ok "redis extension available" || warn "redis extension missing — Postwoo falls back to file cache (fine for one host)"
# W15 video tools: optional. Without ffmpeg/ffprobe videos still upload and publish unchanged.
if command -v ffmpeg >/dev/null && command -v ffprobe >/dev/null; then ok "ffmpeg + ffprobe available (video trim/crop/covers/captions)"; else warn "ffmpeg/ffprobe missing — video tools are disabled (apt install ffmpeg, or set FFMPEG_PATH/FFPROBE_PATH); check later with: php bin/postwoo video:check"; fi

# ── 2. Environment ──────────────────────────────────────────────────────────
bold "2/6 Environment (.env)"
if [ ! -f .env ]; then cp .env.example .env; ok "Created .env from .env.example"; else ok ".env exists — keeping your values"; fi
if [ "$UPGRADE" = 0 ]; then
  ask APP_URL "Public URL of this installation (https://…)" "$(grep -E '^APP_URL=' .env | cut -d= -f2- | sed 's/[[:space:]]*#.*$//')"
  [ -n "$APP_URL" ] || die "APP_URL is required."
  case "$APP_URL" in https://*|http://localhost*|http://127.0.0.1*) ;; *) warn "APP_URL is not https — platforms will refuse OAuth redirects and media fetches on a public host.";; esac
  ask DB_DRIVER "Database driver (mysql or sqlite)" "mysql"
  case "$DB_DRIVER" in
    mysql)
      php -m | grep -qi '^pdo_mysql$' || die "pdo_mysql extension missing."
      ask DB_HOST "MySQL host" "$DB_HOST"; ask DB_PORT "MySQL port" "$DB_PORT"; ask DB_NAME "Database name" "$DB_NAME"; ask DB_USER "Database user" "$DB_USER"; ask DB_PASS "Database password" "" secret
      ;;
    sqlite) php -m | grep -qi '^pdo_sqlite$' || die "pdo_sqlite extension missing."; warn "SQLite is fine for a single-host install; use MySQL 8 for multi-worker production.";;
    *) die "--db must be mysql or sqlite";;
  esac
  FORCE=1 set_env APP_URL "$APP_URL"
  FORCE=1 set_env APP_ENV "$ENV_NAME"
  FORCE=1 set_env APP_DEBUG "$([ "$ENV_NAME" = production ] && echo false || echo true)"
  FORCE=1 set_env DB_DRIVER "$DB_DRIVER"
  if [ "$DB_DRIVER" = mysql ]; then FORCE=1 set_env DB_HOST "$DB_HOST"; FORCE=1 set_env DB_PORT "$DB_PORT"; FORCE=1 set_env DB_DATABASE "$DB_NAME"; FORCE=1 set_env DB_USERNAME "$DB_USER"; FORCE=1 set_env DB_PASSWORD "$DB_PASS"; fi
  case "$APP_URL" in https://*) FORCE=1 set_env SESSION_SECURE_COOKIE true;; esac
  if ! grep -qE '^REDIS_URL=redis' .env || ! php -m | grep -qi '^redis$'; then set_env REDIS_URL ""; fi
  ok "Wrote APP_URL, APP_ENV, database settings"
fi

if grep -qE '^APP_KEY=\s*$' .env; then php bin/postwoo key:generate >/dev/null && ok "Generated APP_KEY (back it up: without it stored OAuth tokens are unreadable)"; else ok "APP_KEY already set"; fi

# ── 3. Storage ──────────────────────────────────────────────────────────────
bold "3/6 Storage directories"
mkdir -p storage/logs storage/cache storage/uploads storage/sessions storage/backups
chmod -R u+rwX,g+rwX storage
if [ -n "$WEB_USER" ]; then
  if id "$WEB_USER" >/dev/null 2>&1; then chown -R "$WEB_USER":"$WEB_USER" storage 2>/dev/null && ok "storage/ owned by $WEB_USER" || warn "Could not chown storage/ (run as root to do that)"; else warn "User $WEB_USER does not exist; skipped chown"; fi
else ok "storage/ writable by $(id -un) (pass --web-user=www-data to chown for the web server)"; fi

# ── 4. Database ─────────────────────────────────────────────────────────────
bold "4/6 Database"
for i in $(seq 1 15); do if php bin/postwoo db:check >/dev/null 2>&1; then break; fi; [ "$i" = 15 ] && { php bin/postwoo db:check || die "Cannot connect to the database. Check the DB_* values in .env."; }; sleep 2; done
php bin/postwoo db:check
php bin/postwoo migrate
ok "Migrations applied"

if [ "$UPGRADE" = 1 ]; then
  if systemctl list-units --type=service 2>/dev/null | grep -q postwoo-worker; then systemctl restart postwoo-worker && ok "Restarted postwoo-worker"; fi
  bold "Upgrade complete."; exit 0
fi

# ── 5. First admin + organization ───────────────────────────────────────────
bold "5/6 First user and organization"
ask ADMIN_EMAIL "Admin e-mail (leave empty to skip)" ""
if [ -n "$ADMIN_EMAIL" ]; then
  ask ADMIN_NAME "Admin name" "Admin"
  ask ADMIN_PASS "Admin password (min 12 chars)" "" secret
  [ "${#ADMIN_PASS}" -ge 12 ] || die "Password must be at least 12 characters."
  if php bin/postwoo user:create --email="$ADMIN_EMAIL" --name="$ADMIN_NAME" --password="$ADMIN_PASS" --superadmin >/dev/null 2>&1; then ok "Created superadmin $ADMIN_EMAIL"; else warn "User $ADMIN_EMAIL already exists — kept as is"; fi
  ask ORG_NAME "Organization (your agency) name" "My Agency"
  if php bin/postwoo org:create --name="$ORG_NAME" --owner="$ADMIN_EMAIL" >/dev/null 2>&1; then ok "Created organization \"$ORG_NAME\" owned by $ADMIN_EMAIL"; else warn "Organization \"$ORG_NAME\" could not be created (it may already exist)"; fi
else warn "Skipped user creation — run: php bin/postwoo user:create --email=… --name=… --password=… --superadmin && php bin/postwoo org:create --name=… --owner=…"; fi
if [ "$DEMO" = 1 ]; then php bin/postwoo demo:seed | tail -3; ok "Demo workspace seeded (clearly labelled sample data)"; fi

# ── 6. Services ─────────────────────────────────────────────────────────────
bold "6/6 Background services"
if [ "$SYSTEMD" = 1 ]; then
  [ "$(id -u)" = 0 ] || die "--systemd needs root (sudo)."
  RUN_USER="${WEB_USER:-www-data}"
  sed -e "s|/var/www/postwoo|$ROOT|g" -e "s|User=www-data|User=$RUN_USER|" docker/postwoo-worker.service > /etc/systemd/system/postwoo-worker.service
  systemctl daemon-reload && systemctl enable --now postwoo-worker && ok "postwoo-worker.service installed and started (user $RUN_USER)"
  CRON_LINE="* * * * * cd $ROOT && php bin/postwoo schedule:run >> storage/logs/schedule.log 2>&1"
  ( crontab -u "$RUN_USER" -l 2>/dev/null | grep -v 'postwoo schedule:run' ; echo "$CRON_LINE" ) | crontab -u "$RUN_USER" - && ok "Scheduler cron installed for $RUN_USER (every minute)"
  BACKUP_LINE="15 2 * * * cd $ROOT && php bin/postwoo db:backup --keep=14 >> storage/logs/backup.log 2>&1"
  ( crontab -u "$RUN_USER" -l 2>/dev/null | grep -v 'postwoo db:backup' ; echo "$BACKUP_LINE" ) | crontab -u "$RUN_USER" - && ok "Nightly backup cron installed (02:15)"
else
  warn "Worker and scheduler not installed. Either re-run with: sudo bash install.sh --systemd --web-user=www-data"
  echo "     or run them yourself:  php bin/postwoo queue:work --queue=publishing,sync,default --max-seconds=3600   (supervised)"
  echo "                            * * * * * php bin/postwoo schedule:run                                      (cron)"
fi

bold "Done."
cat <<SUMMARY

  Web root ........ $ROOT/public   (point your virtual host here; samples in deploy/nginx.conf.example and deploy/apache-vhost.conf.example)
  App URL ......... $APP_URL
  Sign in ......... $APP_URL/login
  API docs ........ $APP_URL/docs        Help: $APP_URL/help
  Health check .... $APP_URL/health

  Next steps
  1. Put the social platform credentials in .env (GOOGLE_CLIENT_ID/SECRET, META_APP_ID/SECRET, LINKEDIN_*, YOUTUBE_*, TIKTOK_*) — see $APP_URL/help/connect-social-platforms.
     Redirect URI for every platform: $APP_URL/oauth/{platform}/callback
  2. Set MAIL_* for alert and digest e-mails, and STORAGE_DRIVER=s3 + S3_* so platforms can fetch media from a public bucket.
  3. php bin/postwoo health:check   ·   php bin/postwoo integrations:report
  4. Back up APP_KEY from .env in your secret store (docs/runbooks/backup-restore.md).
SUMMARY
