#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  bootstrap-node-site --domain DOMAIN --node-version 18|20|22 [--repo /srv/git/DOMAIN] [--port PORT] [--issue-cert] [--email EMAIL] [--runtime-command CMD] [--site-greeting TEXT] [--app-url URL] [--force]
  bootstrap-node-site --help

What it does:
  - creates a minimal Node repo skeleton under /srv/git/DOMAIN if missing
  - initializes git metadata for the skeleton, including package-lock.json
  - creates the Nginx/systemd/site-root scaffold with create-node-site
  - seeds shared .env.local with init-node-shared-env
  - performs the first deployment with cicd-deploy-node-site

Notes:
  - run as root
  - if the repo already exists, the skeleton step is skipped unless --force is used
  - without --issue-cert the generated APP_URL defaults to http://DOMAIN
EOF
}

require_root() {
  [[ ${EUID:-$(id -u)} -eq 0 ]] || { echo 'Run as root' >&2; exit 1; }
}

domain=""
node_version=""
repo=""
port=""
issue_cert=0
email=""
runtime_command="node server.js"
site_greeting=""
app_url=""
force=0

while [[ $# -gt 0 ]]; do
  case "$1" in
    --domain) domain="${2:-}"; shift 2 ;;
    --node-version) node_version="${2:-}"; shift 2 ;;
    --repo) repo="${2:-}"; shift 2 ;;
    --port) port="${2:-}"; shift 2 ;;
    --issue-cert) issue_cert=1; shift ;;
    --email) email="${2:-}"; shift 2 ;;
    --runtime-command) runtime_command="${2:-}"; shift 2 ;;
    --site-greeting) site_greeting="${2:-}"; shift 2 ;;
    --app-url) app_url="${2:-}"; shift 2 ;;
    --force) force=1; shift ;;
    --help|-h) usage; exit 0 ;;
    *) echo "Unknown argument: $1" >&2; usage; exit 2 ;;
  esac
done

[[ -n "$domain" && -n "$node_version" ]] || { usage; exit 2; }
require_root

case "$node_version" in
  18|20|22) ;;
  *) echo "Unsupported node version: $node_version" >&2; exit 2 ;;
esac

if [[ -z "$repo" ]]; then
  repo="/srv/git/$domain"
fi
if [[ -z "$site_greeting" ]]; then
  site_greeting="hello-from-bootstrap-node${node_version}"
fi
if [[ -z "$app_url" ]]; then
  if [[ "$issue_cert" -eq 1 ]]; then
    app_url="https://$domain"
  else
    app_url="http://$domain"
  fi
fi

mkdir -p /srv/git
chown git:git /srv/git
chmod 2775 /srv/git

need_skeleton=0
if [[ ! -d "$repo" ]]; then
  need_skeleton=1
elif [[ "$force" -eq 1 ]]; then
  need_skeleton=1
fi

if [[ "$need_skeleton" -eq 1 ]]; then
  sudo -u git bash -lc "rm -rf '$repo' && mkdir -p '$repo'"
  tmpdir=$(mktemp -d)
  cat > "$tmpdir/package.json" <<EOF_JSON
{
  "name": "${domain//./-}",
  "version": "1.0.0",
  "private": true,
  "description": "Bootstrap Node${node_version} site for $domain",
  "engines": {
    "node": "${node_version}.x"
  },
  "scripts": {
    "build": "node -e \"console.log('build ok')\"",
    "start": "${runtime_command}"
  }
}
EOF_JSON
  cat > "$tmpdir/server.js" <<'EOF_JS'
const http = require('http');
const os = require('os');
const path = require('path');

const host = process.env.HOST || '127.0.0.1';
const port = Number(process.env.PORT || 3000);
const payload = () => ({
  ok: true,
  domain: process.env.APP_DOMAIN || process.env.APP_NAME || 'unknown',
  url: process.env.APP_URL || '',
  node_version: process.version,
  node_env: process.env.NODE_ENV || '',
  hostname: os.hostname(),
  cwd: process.cwd(),
  release_file: path.join(process.cwd(), 'server.js'),
  site_greeting: process.env.SITE_GREETING || '',
  timestamp: new Date().toISOString(),
});

const server = http.createServer((req, res) => {
  const data = payload();
  if (req.url === '/healthz') {
    res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
    return res.end(JSON.stringify(data, null, 2));
  }
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end([
    data.domain,
    'deployed_by=bootstrap-node-site',
    `node_version=${data.node_version}`,
    `node_env=${data.node_env}`,
    `site_greeting=${data.site_greeting}`,
    `app_url=${data.url}`,
    `cwd=${data.cwd}`,
    `release_file=${data.release_file}`,
    `timestamp=${data.timestamp}`,
  ].join('\n'));
});

server.listen(port, host, () => {
  console.log(`listening on http://${host}:${port}`);
});
EOF_JS
  printf 'node_modules/\n.next/\nnpm-debug.log*\n' > "$tmpdir/.gitignore"
  printf '%s\n' "$node_version" > "$tmpdir/.node-version"
  install -d -o git -g git "$repo"
  install -o git -g git -m 0644 "$tmpdir/package.json" "$repo/package.json"
  install -o git -g git -m 0644 "$tmpdir/server.js" "$repo/server.js"
  install -o git -g git -m 0644 "$tmpdir/.gitignore" "$repo/.gitignore"
  install -o git -g git -m 0644 "$tmpdir/.node-version" "$repo/.node-version"
  rm -rf "$tmpdir"
  /usr/local/bin/node-with-fnm --user git --version "$node_version" --shell-command "cd '$repo' && npm install --package-lock-only"
  chown git:git "$repo/package-lock.json"
  sudo -u git bash -lc "cd '$repo' && git init -b main && git add package.json package-lock.json server.js .gitignore .node-version && git -c user.name='Hermes Bootstrap' -c user.email='hermes@localhost' commit -m 'Bootstrap Node${node_version} site skeleton'"
else
  echo "Repo already exists, reusing: $repo"
fi

create_args=(/usr/local/bin/create-node-site --domain "$domain" --node-version "$node_version" --start-command "npm start")
if [[ -n "$port" ]]; then
  create_args+=(--port "$port")
fi
if [[ "$force" -eq 1 ]]; then
  create_args+=(--force)
fi
if [[ "$issue_cert" -eq 1 ]]; then
  create_args+=(--issue-cert)
  if [[ -n "$email" ]]; then
    create_args+=(--email "$email")
  fi
fi
"${create_args[@]}"

/usr/local/bin/init-node-shared-env --domain "$domain" --file .env.local --force --set "SITE_GREETING=$site_greeting" --set "APP_URL=$app_url"
/usr/local/bin/cicd-deploy-node-site --domain "$domain" --healthcheck-expect "$site_greeting"

echo "Bootstrapped Node site: $domain"
echo "Repo: $repo"
echo "Greeting: $site_greeting"
echo "App URL: $app_url"
