#!/usr/bin/env bash
#
# Automatic installer for the SaaS POS platform.
# Builds a fresh Laravel 11 app, overlays this scaffold (already wired — no manual
# file edits), creates the central database, migrates, and provisions your first
# tenant. Run it from inside the unzipped scaffold folder.
#
# What it does NOT do (these live outside the server and can't be scripted safely):
#   • wildcard DNS record  *.yourdomain.com  -> this server
#   • TLS certificate for the wildcard / tenant custom domains
# It DOES generate a ready-to-use nginx vhost file for you to drop in.
#
# Usage:
#   ./install.sh --domain yourdomain.com [options]
#
# Common options (anything omitted is prompted, or has a default):
#   --domain <d>            Central domain (required), e.g. yourdomain.com
#   --app-dir <path>        Where to build the app           (default: ~/saas-pos)
#   --db-name <n>           Central database name             (default: saas_central)
#   --db-user <u>           App DB user                       (default: saas_user)
#   --db-pass <p>           App DB password                   (prompted if unset)
#   --db-host <h>           (default: 127.0.0.1)   --db-port <p> (default: 3306)
#   --mysql-root-user <u>   If given, the script creates the DB + app user with the
#   --mysql-root-pass <p>   needed CREATE-DATABASE privileges automatically.
#   --tenant-domain <d>     First tenant domain   (default: demo.<central domain>)
#   --tenant-name "<n>"     First tenant name                 (default: "Demo Store")
#   --admin-email <e>       Owner email for the first tenant
#   --no-demo               Skip demo products/invoices
#   -h, --help              Show this help

set -euo pipefail

# ---- defaults (overridable by env or flags) ----
APP_DIR="${APP_DIR:-$HOME/saas-pos}"
CENTRAL_DOMAIN="${CENTRAL_DOMAIN:-}"
DB_HOST="${DB_HOST:-127.0.0.1}"; DB_PORT="${DB_PORT:-3306}"
DB_DATABASE="${DB_DATABASE:-saas_central}"
DB_USERNAME="${DB_USERNAME:-saas_user}"; DB_PASSWORD="${DB_PASSWORD:-}"
MYSQL_ROOT_USER="${MYSQL_ROOT_USER:-}"; MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-}"
FIRST_TENANT_DOMAIN="${FIRST_TENANT_DOMAIN:-}"
FIRST_TENANT_NAME="${FIRST_TENANT_NAME:-Demo Store}"
ADMIN_EMAIL="${ADMIN_EMAIL:-owner@example.com}"
WITH_DEMO="${WITH_DEMO:-1}"

SCAFFOLD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

c()  { printf '\033[%sm%s\033[0m' "$1" "$2"; }
say() { printf '\n%s %s\n' "$(c '1;36' '==>')" "$1"; }
ok()  { printf '%s %s\n' "$(c '1;32' '  ✓')" "$1"; }
die() { printf '%s %s\n' "$(c '1;31' 'ERROR:')" "$1" >&2; exit 1; }

while [ $# -gt 0 ]; do
  case "$1" in
    --domain) CENTRAL_DOMAIN="$2"; shift 2;;
    --app-dir) APP_DIR="$2"; shift 2;;
    --db-name) DB_DATABASE="$2"; shift 2;;
    --db-user) DB_USERNAME="$2"; shift 2;;
    --db-pass) DB_PASSWORD="$2"; shift 2;;
    --db-host) DB_HOST="$2"; shift 2;;
    --db-port) DB_PORT="$2"; shift 2;;
    --mysql-root-user) MYSQL_ROOT_USER="$2"; shift 2;;
    --mysql-root-pass) MYSQL_ROOT_PASSWORD="$2"; shift 2;;
    --tenant-domain) FIRST_TENANT_DOMAIN="$2"; shift 2;;
    --tenant-name) FIRST_TENANT_NAME="$2"; shift 2;;
    --admin-email) ADMIN_EMAIL="$2"; shift 2;;
    --no-demo) WITH_DEMO=""; shift;;
    -h|--help) sed -n '2,40p' "$0"; exit 0;;
    *) die "Unknown option: $1";;
  esac
done

# ---- prompts for required-but-missing values ----
if [ -z "$CENTRAL_DOMAIN" ]; then
  [ -t 0 ] || die "--domain is required."
  read -rp "Central domain (e.g. yourdomain.com): " CENTRAL_DOMAIN
fi
[ -n "$CENTRAL_DOMAIN" ] || die "Central domain cannot be empty."
if [ -z "$DB_PASSWORD" ]; then
  if [ -t 0 ]; then read -rsp "Database password for '$DB_USERNAME': " DB_PASSWORD; echo
  else die "--db-pass is required in non-interactive mode."; fi
fi
[ -n "$FIRST_TENANT_DOMAIN" ] || FIRST_TENANT_DOMAIN="demo.$CENTRAL_DOMAIN"

# ---- prerequisite checks ----
say "Checking prerequisites"
command -v php >/dev/null      || die "PHP not found. Install PHP 8.2+ and required extensions."
php -r 'exit(version_compare(PHP_VERSION,"8.2.0",">=")?0:1);' || die "PHP 8.2+ required (found $(php -r 'echo PHP_VERSION;'))."
command -v composer >/dev/null || die "Composer not found. Install Composer 2."
command -v mysql >/dev/null    || die "mysql client not found. Install the MySQL/MariaDB client."
ok "php $(php -r 'echo PHP_VERSION;'), composer, mysql present"

[ -e "$APP_DIR" ] && [ -n "$(ls -A "$APP_DIR" 2>/dev/null || true)" ] && die "Target '$APP_DIR' exists and isn't empty. Pick another --app-dir."

# ---- 1. Laravel + tenancy ----
say "Creating Laravel app at $APP_DIR"
composer create-project laravel/laravel "$APP_DIR" "^11.0" --no-interaction
cd "$APP_DIR"
say "Installing stancl/tenancy"
composer require "stancl/tenancy:^3.8" --no-interaction
php artisan tenancy:install -n >/dev/null
ok "tenancy installed"

# ---- 2. Overlay scaffold (merge contents) + pre-wired framework files ----
say "Applying the POS scaffold"
for d in app config database routes resources; do
  mkdir -p "./$d"
  cp -R "$SCAFFOLD_DIR/$d/." "./$d/"
done
cp "$SCAFFOLD_DIR/install/bootstrap-app.php"            "./bootstrap/app.php"
cp "$SCAFFOLD_DIR/install/TenancyServiceProvider.php"   "./app/Providers/TenancyServiceProvider.php"
ok "files in place (CSRF + tenant seeding pre-wired)"

# ---- 3. Environment ----
say "Writing .env"
cat > .env <<ENVEOF
APP_NAME="SaaS POS"
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://$CENTRAL_DOMAIN

LOG_CHANNEL=stack
LOG_LEVEL=error

CENTRAL_DOMAIN=$CENTRAL_DOMAIN

DB_CONNECTION=mysql
DB_HOST=$DB_HOST
DB_PORT=$DB_PORT
DB_DATABASE=$DB_DATABASE
DB_USERNAME=$DB_USERNAME
DB_PASSWORD=$DB_PASSWORD

# Kept off the database driver: the default connection switches to the tenant
# during tenant requests, so DB-backed sessions/cache would hit the wrong DB.
SESSION_DRIVER=file
SESSION_LIFETIME=120
CACHE_STORE=file
QUEUE_CONNECTION=sync

PAYMENTS_DEFAULT=myfatoorah
PAYMENTS_CURRENCY=KWD
MYFATOORAH_TOKEN=
MYFATOORAH_BASE_URL=https://apitest.myfatoorah.com
TAP_SECRET_KEY=
TAP_BASE_URL=https://api.tap.company
ENVEOF
php artisan key:generate --force >/dev/null
ok ".env written and app key generated"

# ---- 4. Database ----
say "Preparing the central database"
if [ -n "$MYSQL_ROOT_USER" ]; then
  mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MYSQL_ROOT_USER" ${MYSQL_ROOT_PASSWORD:+-p"$MYSQL_ROOT_PASSWORD"} <<SQL
CREATE DATABASE IF NOT EXISTS \`$DB_DATABASE\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '$DB_USERNAME'@'%' IDENTIFIED BY '$DB_PASSWORD';
CREATE USER IF NOT EXISTS '$DB_USERNAME'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO '$DB_USERNAME'@'%' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* TO '$DB_USERNAME'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
SQL
  ok "database + user created (with database-creation rights for tenants)"
else
  if mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USERNAME" ${DB_PASSWORD:+-p"$DB_PASSWORD"} \
       -e "CREATE DATABASE IF NOT EXISTS \`$DB_DATABASE\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" 2>/dev/null; then
    ok "central database ensured"
  else
    printf '%s\n' "$(c '1;33' '  ! Could not create the database with the app user.')"
    printf '%s\n' "    Create it manually and make sure '$DB_USERNAME' can CREATE DATABASE"
    printf '%s\n' "    (needed for tenant databases). Re-run with --mysql-root-user to automate this."
  fi
fi

# ---- 5. Migrate central schema ----
say "Migrating the central database"
php artisan migrate --force
ok "central schema migrated"

# ---- 6. First tenant (DB created, migrated & seeded automatically) ----
say "Provisioning first tenant: $FIRST_TENANT_DOMAIN"
php artisan app:make-tenant "$FIRST_TENANT_NAME" "$FIRST_TENANT_DOMAIN" \
  --email="$ADMIN_EMAIL" ${WITH_DEMO:+--demo}

# ---- 7. Permissions + a ready nginx vhost ----
chmod -R ug+rwX storage bootstrap/cache 2>/dev/null || true
PHP_SOCK="$(ls /run/php/php*-fpm.sock 2>/dev/null | head -n1 || echo /run/php/php8.3-fpm.sock)"
mkdir -p deploy
cat > "deploy/$CENTRAL_DOMAIN.nginx.conf" <<NGINX
server {
    listen 80;
    server_name $CENTRAL_DOMAIN *.$CENTRAL_DOMAIN;
    root $APP_DIR/public;
    index index.php;

    location / { try_files \$uri \$uri/ /index.php?\$query_string; }

    location ~ \.php\$ {
        fastcgi_pass unix:$PHP_SOCK;
        fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
        include fastcgi_params;
    }
    location ~ /\.(?!well-known).* { deny all; }
}
NGINX
ok "nginx vhost generated: $APP_DIR/deploy/$CENTRAL_DOMAIN.nginx.conf"

# ---- done ----
say "$(c '1;32' 'Installation complete')"
cat <<DONE

App built at:   $APP_DIR
First tenant:   https://$FIRST_TENANT_DOMAIN  (try /pos)

Two things remain — they're outside the server, so do them at your DNS/host:

  1) DNS: add a wildcard A record so tenant subdomains resolve here
         *   A   <this server's public IP>
         @   A   <this server's public IP>

  2) Web server + TLS:
       sudo cp $APP_DIR/deploy/$CENTRAL_DOMAIN.nginx.conf /etc/nginx/sites-available/saas-pos
       sudo ln -s /etc/nginx/sites-available/saas-pos /etc/nginx/sites-enabled/
       sudo nginx -t && sudo systemctl reload nginx
       sudo certbot certonly --manual --preferred-challenges=dns \\
            -d '$CENTRAL_DOMAIN' -d '*.$CENTRAL_DOMAIN'    # wildcard cert, then add the 443 block

Create more tenants any time:
  php artisan app:make-tenant "Acme Store" acme.$CENTRAL_DOMAIN --demo

Payment keys are entered per tenant in-app under Settings → Payment gateways.
DONE
