#!/bin/sh
# GoToSocial Controller for SecuBox
# Manages GoToSocial in a Debian LXC container (glibc for proper bcrypt support)

set -e

VERSION="0.2.0"
GTS_VERSION="0.17.0"

# LXC container settings
LXC_NAME="gotosocial"
LXC_PATH="/srv/lxc"
LXC_ROOTFS="$LXC_PATH/$LXC_NAME/rootfs"
LXC_CONFIG="$LXC_PATH/$LXC_NAME/config"

# Data paths (bind mounted into container)
DATA_PATH="/srv/gotosocial"
CONFIG_FILE="/etc/config/gotosocial"

# Logging
log_info() { logger -t gotosocial -p daemon.info "$1"; echo "[INFO] $1"; }
log_error() { logger -t gotosocial -p daemon.err "$1"; echo "[ERROR] $1" >&2; }
log_warn() { logger -t gotosocial -p daemon.warn "$1"; echo "[WARN] $1"; }

# UCI helpers
get_config() {
	local section="$1"
	local option="$2"
	local default="$3"
	uci -q get "gotosocial.${section}.${option}" || echo "$default"
}

set_config() {
	uci set "gotosocial.$1.$2=$3"
	uci commit gotosocial
}

# LXC helpers
has_lxc() {
	command -v lxc-start >/dev/null 2>&1 && \
	command -v lxc-stop >/dev/null 2>&1
}

lxc_running() {
	lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"
}

lxc_exists() {
	[ -f "$LXC_CONFIG" ] && [ -d "$LXC_ROOTFS" ]
}

# Check if GoToSocial is installed (container exists with binary)
gts_installed() {
	[ -x "$LXC_ROOTFS/opt/gotosocial/gotosocial" ]
}

# Check if GoToSocial is running (LXC container running)
gts_running() {
	lxc_running
}

# =============================================================================
# LXC CONTAINER MANAGEMENT
# =============================================================================

lxc_stop() {
	if lxc_running; then
		log_info "Stopping GoToSocial container..."
		lxc-stop -n "$LXC_NAME" -k 2>/dev/null || true
		sleep 2
	fi
}

lxc_create_rootfs() {
	log_info "Creating Debian rootfs for GoToSocial..."

	mkdir -p "$LXC_PATH/$LXC_NAME"

	# Download Alpine minirootfs (simple and reliable, glibc not needed since
	# GoToSocial binary is statically linked)
	# Actually, use Debian for glibc bcrypt compatibility

	local arch="x86_64"
	case "$(uname -m)" in
		aarch64) arch="aarch64" ;;
		armv7l)  arch="armv7" ;;
	esac

	# Use Alpine minirootfs as base
	local alpine_url="https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/$arch/alpine-minirootfs-3.21.2-$arch.tar.gz"
	local rootfs_tar="/tmp/alpine-gts.tar.gz"

	log_info "Downloading Alpine rootfs..."
	wget -q -O "$rootfs_tar" "$alpine_url" || {
		log_error "Failed to download Alpine rootfs"
		return 1
	}

	log_info "Extracting rootfs..."
	mkdir -p "$LXC_ROOTFS"
	tar -xzf "$rootfs_tar" -C "$LXC_ROOTFS" || {
		log_error "Failed to extract rootfs"
		return 1
	}
	rm -f "$rootfs_tar"

	# Configure Alpine
	cat > "$LXC_ROOTFS/etc/resolv.conf" << 'EOF'
nameserver 1.1.1.1
nameserver 8.8.8.8
EOF

	cat > "$LXC_ROOTFS/etc/apk/repositories" << 'EOF'
https://dl-cdn.alpinelinux.org/alpine/v3.21/main
https://dl-cdn.alpinelinux.org/alpine/v3.21/community
EOF

	# Install gcompat for glibc compatibility (needed for bcrypt)
	log_info "Installing glibc compatibility layer..."
	chroot "$LXC_ROOTFS" /bin/sh -c "
		apk update && apk add --no-cache gcompat libc6-compat sqlite
	" || log_warn "Could not install gcompat (may not be needed)"

	mkdir -p "$LXC_ROOTFS/opt/gotosocial"
	mkdir -p "$LXC_ROOTFS/data"
	mkdir -p "$LXC_ROOTFS/var/log"

	log_info "Alpine rootfs with glibc compatibility created successfully"
}

# Download and install GoToSocial into the container
lxc_install_gotosocial() {
	local version="${1:-$GTS_VERSION}"

	# GoToSocial uses different arch naming
	local gts_arch="amd64"
	case "$(uname -m)" in
		aarch64) gts_arch="arm64" ;;
		armv7l)  gts_arch="armv7" ;;
	esac

	local url="https://codeberg.org/superseriousbusiness/gotosocial/releases/download/v${version}/gotosocial_${version}_linux_${gts_arch}.tar.gz"
	local tmp_dir="/tmp/gotosocial_install"

	log_info "Downloading GoToSocial v${version} for ${arch}..."

	rm -rf "$tmp_dir"
	mkdir -p "$tmp_dir"
	cd "$tmp_dir"

	# Download with curl (handles redirects) or wget
	curl -L -o gotosocial.tar.gz "$url" 2>/dev/null || \
	wget -O gotosocial.tar.gz "$url" || {
		log_error "Failed to download GoToSocial"
		return 1
	}

	# Verify download size (should be >10MB)
	local size=$(stat -c%s gotosocial.tar.gz 2>/dev/null || stat -f%z gotosocial.tar.gz 2>/dev/null || echo 0)
	if [ "$size" -lt 10000000 ]; then
		log_error "Downloaded file too small ($size bytes), likely failed"
		rm -f gotosocial.tar.gz
		return 1
	fi

	tar -xzf gotosocial.tar.gz

	# Install into container rootfs
	cp gotosocial "$LXC_ROOTFS/opt/gotosocial/"
	chmod +x "$LXC_ROOTFS/opt/gotosocial/gotosocial"

	# Copy web assets
	[ -d "web" ] && cp -r web "$LXC_ROOTFS/opt/gotosocial/"

	rm -rf "$tmp_dir"
	log_info "GoToSocial v${version} installed in container"
}

# Create start script inside container
lxc_create_start_script() {
	cat > "$LXC_ROOTFS/opt/start-gotosocial.sh" << 'SCRIPT'
#!/bin/sh
cd /opt/gotosocial

# Wait for data directory to be ready
sleep 2

# Start GoToSocial
exec /opt/gotosocial/gotosocial server start --config-path /data/config.yaml
SCRIPT
	chmod +x "$LXC_ROOTFS/opt/start-gotosocial.sh"
}

# Create LXC configuration
lxc_create_config() {
	local port=$(get_config main port "8484")
	local memory_limit=$(get_config main memory_limit "512M")

	# LXC arch names
	local lxc_arch="x86_64"
	case "$(uname -m)" in
		aarch64) lxc_arch="aarch64" ;;
		armv7l)  lxc_arch="armhf" ;;
	esac

	local mem_bytes=$(echo "$memory_limit" | sed 's/M/000000/;s/G/000000000/')

	cat > "$LXC_CONFIG" << EOF
# GoToSocial LXC Configuration
lxc.uts.name = $LXC_NAME
lxc.rootfs.path = dir:$LXC_ROOTFS
lxc.arch = $lxc_arch

# Network: use host network for binding ports
lxc.net.0.type = none

# Mount data directory
lxc.mount.entry = $DATA_PATH data none bind,create=dir 0 0

# Disable seccomp for compatibility
lxc.seccomp.profile =

# TTY/PTY settings
lxc.tty.max = 0
lxc.pty.max = 256

# cgroup v2 memory limit
lxc.cgroup2.memory.max = $mem_bytes

# Init
lxc.init.cmd = /opt/start-gotosocial.sh
EOF

	log_info "LXC config created at $LXC_CONFIG"
}

# Create data directory structure on host (bind mounted into container)
create_data_dir() {
	log_info "Creating data directories..."
	mkdir -p "$DATA_PATH"/{storage,web}
	log_info "Data directories created at $DATA_PATH"
}

# Generate GoToSocial config (written to DATA_PATH which is bind-mounted as /data in container)
generate_config() {
	local host=$(get_config main host "social.local")
	local port=$(get_config main port "8484")
	local protocol=$(get_config main protocol "https")
	local bind=$(get_config main bind_address "0.0.0.0")
	local instance_name=$(get_config main instance_name "SecuBox Social")
	local instance_desc=$(get_config main instance_description "A SecuBox Fediverse instance")
	local reg_open_val=$(get_config main accounts_registration_open "0")
	local approval_val=$(get_config main accounts_approval_required "1")
	# Convert 0/1 to false/true for YAML
	local reg_open="false"
	local approval="true"
	[ "$reg_open_val" = "1" ] && reg_open="true"
	[ "$approval_val" = "0" ] && approval="false"

	mkdir -p "$DATA_PATH/storage"

	# Note: paths are relative to container where DATA_PATH is mounted as /data
	cat > "$DATA_PATH/config.yaml" <<EOF
# GoToSocial Configuration
# Generated by SecuBox gotosocialctl

host: "$host"
account-domain: "$host"
protocol: "$protocol"
bind-address: "$bind"
port: $port

db-type: "sqlite"
db-address: "/data/gotosocial.db"

storage-backend: "local"
storage-local-base-path: "/data/storage"

web-template-base-dir: "/opt/gotosocial/web/template"
web-asset-base-dir: "/opt/gotosocial/web/assets"

instance-expose-public-timeline: true
instance-expose-suspended: false
instance-expose-suspended-web: false

accounts-registration-open: $reg_open
accounts-approval-required: $approval
accounts-reason-required: true

media-image-max-size: 10485760
media-video-max-size: 41943040
media-description-min-chars: 0
media-description-max-chars: 500
media-remote-cache-days: 30

statuses-max-chars: 5000
statuses-cw-max-chars: 100
statuses-poll-max-options: 6
statuses-poll-option-max-chars: 50
statuses-media-max-files: 6

letsencrypt-enabled: false

oidc-enabled: false

smtp-host: ""
smtp-port: 0

syslog-enabled: false
syslog-protocol: "udp"
syslog-address: "localhost:514"

log-level: "info"
log-db-queries: false

advanced-cookies-samesite: "lax"
advanced-rate-limit-requests: 300
advanced-throttling-multiplier: 8

cache:
  gts:
    account-max-size: 2000
    account-ttl: "30m"
    account-sweep-freq: "1m"
    status-max-size: 2000
    status-ttl: "30m"
    status-sweep-freq: "1m"
EOF

	log_info "Configuration generated at $DATA_PATH/config.yaml"
}

# Install GoToSocial
cmd_install() {
	local version="${1:-$GTS_VERSION}"

	if [ "$(id -u)" -ne 0 ]; then
		log_error "Root required"
		exit 1
	fi

	if ! has_lxc; then
		log_error "LXC not available. Install lxc packages first."
		exit 1
	fi

	log_info "Installing GoToSocial v${version} in LXC container..."

	# Create data directory on host
	create_data_dir

	# Create container if not exists
	if ! lxc_exists; then
		lxc_create_rootfs || exit 1
	fi

	# Install GoToSocial binary into container
	lxc_install_gotosocial "$version" || exit 1

	# Create start script
	lxc_create_start_script

	# Create LXC config
	lxc_create_config || exit 1

	# Generate GoToSocial config
	generate_config

	log_info "GoToSocial installed successfully"
	log_info "Run 'gotosocialctl start' to start the service"
	log_info "Then create a user with 'gotosocialctl user create <username> <email>'"
}

# Uninstall
cmd_uninstall() {
	local keep_data="$1"

	if [ "$(id -u)" -ne 0 ]; then
		log_error "Root required"
		exit 1
	fi

	log_info "Uninstalling GoToSocial..."

	# Stop container if running
	lxc_stop

	# Remove container
	if [ -d "$LXC_PATH/$LXC_NAME" ]; then
		rm -rf "$LXC_PATH/$LXC_NAME"
		log_info "Container removed"
	fi

	# Remove data unless --keep-data
	if [ "$keep_data" != "--keep-data" ]; then
		rm -rf "$DATA_PATH"
		log_info "Data removed"
	else
		log_info "Data preserved at $DATA_PATH"
	fi

	log_info "GoToSocial uninstalled"
}

# Start GoToSocial (LXC container)
cmd_start() {
	if ! gts_installed; then
		log_error "GoToSocial not installed. Run 'gotosocialctl install' first."
		return 1
	fi

	if gts_running; then
		log_info "GoToSocial container is already running"
		return 0
	fi

	# Regenerate config in case settings changed
	generate_config

	# Regenerate LXC config
	lxc_create_config

	log_info "Starting GoToSocial container..."

	# Start in background
	lxc-start -n "$LXC_NAME" -d || {
		log_error "Failed to start GoToSocial container"
		return 1
	}

	# Wait for startup (WASM compilation takes time on first run)
	local port=$(get_config main port "8484")
	local count=0
	while [ $count -lt 120 ]; do
		sleep 2
		if curl -s --connect-timeout 1 "http://127.0.0.1:$port/api/v1/instance" >/dev/null 2>&1; then
			log_info "GoToSocial started"
			log_info "Web interface available at http://localhost:$port"
			return 0
		fi
		if ! lxc_running; then
			log_error "GoToSocial container stopped unexpectedly"
			log_error "Check: lxc-attach -n gotosocial -- cat /var/log/gotosocial.log"
			return 1
		fi
		count=$((count + 1))
	done

	log_error "GoToSocial startup timeout. Container still running, may need more time."
	return 1
}

# Stop GoToSocial (LXC container)
cmd_stop() {
	if ! gts_running; then
		log_info "GoToSocial is not running"
		return 0
	fi

	log_info "Stopping GoToSocial..."
	lxc_stop
	log_info "GoToSocial stopped"
}

# Restart
cmd_restart() {
	cmd_stop
	sleep 1
	cmd_start
}

# Reload config
cmd_reload() {
	log_info "Reloading configuration..."
	generate_config
	cmd_restart
}

# Status (JSON output for RPCD)
cmd_status() {
	local installed="false"
	local running="false"
	local service_state="false"
	local host=$(get_config main host "social.example.com")
	local port=$(get_config main port "8484")
	local version=$(get_config container version "$GTS_VERSION")
	local tor_enabled=$(get_config federation tor_enabled "0")
	local dns_enabled=$(get_config proxy enabled "0")
	local mesh_enabled=$(get_config mesh announce_to_peers "0")

	gts_installed && installed="true"
	gts_running && running="true"

	# Check if API responds
	if [ "$running" = "true" ]; then
		curl -s --connect-timeout 2 "http://127.0.0.1:$port/api/v1/instance" >/dev/null 2>&1 && service_state="true"
	fi

	cat <<EOF
{
	"installed": $installed,
	"container_running": $running,
	"service_running": $service_state,
	"host": "$host",
	"port": "$port",
	"version": "$version",
	"tor_enabled": $([ "$tor_enabled" = "1" ] && echo "true" || echo "false"),
	"dns_enabled": $([ "$dns_enabled" = "1" ] && echo "true" || echo "false"),
	"mesh_enabled": $([ "$mesh_enabled" = "1" ] && echo "true" || echo "false")
}
EOF
}

# Status (human readable)
cmd_status_human() {
	if gts_running; then
		echo "GoToSocial: running (LXC container)"

		local port=$(get_config main port "8484")
		local host=$(get_config main host "localhost")
		echo "Host: $host"
		echo "Port: $port"
		echo "Container: $LXC_NAME"

		# Check if web interface responds
		if curl -s --connect-timeout 2 "http://127.0.0.1:$port/api/v1/instance" >/dev/null 2>&1; then
			echo "API: responding"
		else
			echo "API: not responding (may still be starting)"
		fi
	else
		echo "GoToSocial: stopped"
		if gts_installed; then
			echo "Container: installed but not running"
		else
			echo "Container: not installed"
		fi
		return 1
	fi
}

# Shell access to container
cmd_shell() {
	if ! gts_running; then
		log_error "Container not running. Start with 'gotosocialctl start' first."
		return 1
	fi

	lxc-attach -n "$LXC_NAME" -- /bin/sh
}

# Helper to run GoToSocial admin commands
gts_admin_cmd() {
	# Commands can run with container stopped (just need rootfs + data)
	# Use chroot to run the binary
	if lxc_running; then
		# Container running - use lxc-attach
		lxc-attach -n "$LXC_NAME" -- /opt/gotosocial/gotosocial "$@"
	else
		# Container stopped - use chroot with bind mounts
		# Mount data directory temporarily
		mount --bind "$DATA_PATH" "$LXC_ROOTFS/data" 2>/dev/null || true
		chroot "$LXC_ROOTFS" /opt/gotosocial/gotosocial "$@"
		local ret=$?
		umount "$LXC_ROOTFS/data" 2>/dev/null || true
		return $ret
	fi
}

# Create user
cmd_user_create() {
	local username="$1"
	local email="$2"
	local password="$3"
	local admin="${4:-false}"

	[ -z "$username" ] || [ -z "$email" ] && {
		echo "Usage: gotosocialctl user create <username> <email> [password] [--admin]"
		return 1
	}

	[ "$3" = "--admin" ] && { admin="true"; password=""; }
	[ "$4" = "--admin" ] && admin="true"

	if ! gts_installed; then
		log_error "GoToSocial is not installed"
		return 1
	fi

	log_info "Creating user $username..."

	# Generate random password if not provided
	[ -z "$password" ] && password=$(openssl rand -base64 12)

	gts_admin_cmd admin account create \
		--username "$username" \
		--email "$email" \
		--password "$password" \
		--config-path "/data/config.yaml"

	if [ "$admin" = "true" ]; then
		gts_admin_cmd admin account promote \
			--username "$username" \
			--config-path "/data/config.yaml"
	fi

	# Confirm the user
	gts_admin_cmd admin account confirm \
		--username "$username" \
		--config-path "/data/config.yaml" 2>/dev/null || true

	echo ""
	echo "User created successfully!"
	echo "Username: $username"
	echo "Email: $email"
	echo "Password: $password"
	echo ""
	echo "Please change this password after first login."
}

# List users (JSON output for RPCD)
cmd_users() {
	local db_path="$DATA_PATH/gotosocial.db"
	local users="[]"

	if [ -f "$db_path" ] && command -v sqlite3 >/dev/null; then
		users=$(sqlite3 -json "$db_path" "SELECT username, created_at as created,
			CASE WHEN suspended_at IS NULL THEN 0 ELSE 1 END as suspended,
			CASE WHEN confirmed_at IS NULL THEN 0 ELSE 1 END as confirmed
			FROM accounts WHERE domain IS NULL OR domain = '';" 2>/dev/null || echo "[]")
	fi

	echo "{\"users\":$users}"
}

# List users (human readable)
cmd_user_list() {
	local db_path="$DATA_PATH/gotosocial.db"

	if [ -f "$db_path" ] && command -v sqlite3 >/dev/null; then
		sqlite3 "$db_path" "SELECT username, created_at, suspended_at FROM accounts WHERE domain IS NULL OR domain = '';" 2>/dev/null || {
			echo "Unable to query database directly. Use the web interface."
		}
	else
		echo "Use the web interface to manage users."
		echo "URL: https://$(get_config main host)/admin"
	fi
}

# Confirm user email
cmd_user_confirm() {
	local username="$1"

	[ -z "$username" ] && {
		echo "Usage: gotosocialctl user confirm <username>"
		return 1
	}

	if ! gts_installed; then
		log_error "GoToSocial is not installed"
		return 1
	fi

	gts_admin_cmd admin account confirm \
		--username "$username" \
		--config-path "/data/config.yaml"

	log_info "User $username confirmed"
}

# Reset user password
cmd_user_password() {
	local username="$1"
	local password="$2"

	[ -z "$username" ] && {
		echo "Usage: gotosocialctl user password <username> [new-password]"
		return 1
	}

	if ! gts_installed; then
		log_error "GoToSocial is not installed"
		return 1
	fi

	# Generate random password if not provided
	[ -z "$password" ] && password=$(openssl rand -base64 12)

	gts_admin_cmd admin account password \
		--username "$username" \
		--password "$password" \
		--config-path "/data/config.yaml"

	echo ""
	echo "Password reset for $username"
	echo "New password: $password"
}

# Emancipate - expose via HAProxy
cmd_emancipate() {
	local domain="$1"

	[ -z "$domain" ] && domain=$(get_config main host)
	[ -z "$domain" ] || [ "$domain" = "social.example.com" ] && {
		echo "Usage: gotosocialctl emancipate <domain>"
		echo "Example: gotosocialctl emancipate social.mysite.com"
		return 1
	}

	local port=$(get_config main port "8484")
	local lan_ip=$(uci -q get network.lan.ipaddr || echo "192.168.255.1")

	log_info "Exposing GoToSocial at $domain..."

	# Update config
	set_config main host "$domain"
	set_config proxy enabled "1"
	set_config proxy vhost_domain "$domain"

	# Create HAProxy backend
	uci set haproxy.gotosocial=backend
	uci set haproxy.gotosocial.name='gotosocial'
	uci set haproxy.gotosocial.mode='http'
	uci set haproxy.gotosocial.balance='roundrobin'
	uci set haproxy.gotosocial.enabled='1'

	uci set haproxy.gotosocial_srv=server
	uci set haproxy.gotosocial_srv.backend='gotosocial'
	uci set haproxy.gotosocial_srv.name='gotosocial'
	uci set haproxy.gotosocial_srv.address="$lan_ip"
	uci set haproxy.gotosocial_srv.port="$port"
	uci set haproxy.gotosocial_srv.weight='100'
	uci set haproxy.gotosocial_srv.check='1'
	uci set haproxy.gotosocial_srv.enabled='1'

	# Create vhost
	local vhost_name=$(echo "$domain" | tr '.-' '_')
	uci set haproxy.${vhost_name}=vhost
	uci set haproxy.${vhost_name}.domain="$domain"
	uci set haproxy.${vhost_name}.backend='gotosocial'
	uci set haproxy.${vhost_name}.ssl='1'
	uci set haproxy.${vhost_name}.ssl_redirect='1'
	uci set haproxy.${vhost_name}.acme='1'
	uci set haproxy.${vhost_name}.enabled='1'

	uci commit haproxy
	uci commit gotosocial

	# Regenerate HAProxy config
	if command -v haproxyctl >/dev/null; then
		haproxyctl generate
		/etc/init.d/haproxy reload
	fi

	# Regenerate GoToSocial config with new domain
	generate_config

	# Restart to apply new config
	gts_running && cmd_restart

	log_info "GoToSocial exposed at https://$domain"
	log_info "SSL certificate will be provisioned automatically"
}

# Backup
cmd_backup() {
	local backup_path="${1:-/tmp/gotosocial-backup-$(date +%Y%m%d-%H%M%S).tar.gz}"

	log_info "Creating backup..."

	# Stop for consistent backup
	local was_running=false
	if gts_running; then
		was_running=true
		cmd_stop
	fi

	tar -czf "$backup_path" -C "$DATA_PATH" . 2>/dev/null || {
		log_error "Backup failed"
		[ "$was_running" = "true" ] && cmd_start
		return 1
	}

	[ "$was_running" = "true" ] && cmd_start

	log_info "Backup created: $backup_path"
	ls -lh "$backup_path"
}

# Restore
cmd_restore() {
	local backup_path="$1"

	[ -z "$backup_path" ] || [ ! -f "$backup_path" ] && {
		echo "Usage: gotosocialctl restore <backup-file>"
		return 1
	}

	log_info "Restoring from $backup_path..."

	# Stop if running
	gts_running && cmd_stop

	# Clear existing data
	rm -rf "$DATA_PATH"/*

	# Extract backup
	tar -xzf "$backup_path" -C "$DATA_PATH" || {
		log_error "Restore failed"
		return 1
	}

	log_info "Restore complete"
	cmd_start
}

# Federation commands
cmd_federation_list() {
	local port=$(get_config main port "8484")

	curl -s "http://127.0.0.1:$port/api/v1/instance/peers" 2>/dev/null | jq -r '.[]' 2>/dev/null || {
		echo "Unable to fetch federation list. Is GoToSocial running?"
	}
}

# Show logs (JSON output)
cmd_logs() {
	local lines="${1:-50}"
	local logs

	logs=$(logread -e gotosocial 2>/dev/null | tail -n "$lines" | jq -R -s 'split("\n") | map(select(length > 0))' 2>/dev/null || echo "[]")

	echo "{\"logs\":$logs}"
}

# Show help
cmd_help() {
	cat <<EOF
GoToSocial Controller for SecuBox v$VERSION
Runs GoToSocial in a Debian LXC container (glibc-based for proper bcrypt support)

Usage: gotosocialctl <command> [options]

Installation:
  install [version]       Install GoToSocial (default: v$GTS_VERSION)
  uninstall [--keep-data] Remove GoToSocial
  update [version]        Update to new version

Service:
  start                   Start GoToSocial container
  stop                    Stop GoToSocial container
  restart                 Restart GoToSocial
  reload                  Reload configuration
  status                  Show status (JSON)
  status-human            Show status (human readable)

User Management:
  user create <user> <email> [password] [--admin]  Create user
  user list               List users
  user confirm <user>     Confirm user email
  user password <user> [pwd]  Reset user password

Exposure:
  emancipate <domain>     Expose via HAProxy + SSL

Container:
  shell                   Open shell in container

Backup:
  backup [path]           Backup data
  restore <path>          Restore from backup

Federation:
  federation list         List federated instances

Other:
  help                    Show this help
  version                 Show version

Examples:
  gotosocialctl install
  gotosocialctl start
  gotosocialctl user create alice alice@example.com --admin
  gotosocialctl user password alice newpassword123
  gotosocialctl emancipate social.mysite.com

EOF
}

# Main
case "$1" in
	install)
		cmd_install "$2"
		;;
	uninstall)
		cmd_uninstall "$2"
		;;
	update)
		cmd_stop
		lxc_install_gotosocial "${2:-$GTS_VERSION}"
		cmd_start
		;;
	start)
		cmd_start
		;;
	stop)
		cmd_stop
		;;
	restart)
		cmd_restart
		;;
	reload)
		cmd_reload
		;;
	status)
		cmd_status
		;;
	status-human)
		cmd_status_human
		;;
	users)
		cmd_users
		;;
	logs)
		cmd_logs "$2"
		;;
	shell)
		cmd_shell
		;;
	user)
		case "$2" in
			create)
				cmd_user_create "$3" "$4" "$5" "$6"
				;;
			list)
				cmd_user_list
				;;
			confirm)
				cmd_user_confirm "$3"
				;;
			password)
				cmd_user_password "$3" "$4"
				;;
			*)
				echo "Usage: gotosocialctl user {create|list|confirm|password}"
				;;
		esac
		;;
	emancipate)
		cmd_emancipate "$2"
		;;
	backup)
		cmd_backup "$2"
		;;
	restore)
		cmd_restore "$2"
		;;
	federation)
		case "$2" in
			list)
				cmd_federation_list
				;;
			*)
				echo "Usage: gotosocialctl federation {list}"
				;;
		esac
		;;
	version)
		echo "gotosocialctl v$VERSION (GoToSocial v$GTS_VERSION)"
		;;
	help|--help|-h|"")
		cmd_help
		;;
	*)
		echo "Unknown command: $1"
		cmd_help
		exit 1
		;;
esac
