#!/bin/sh
# SecuBox MetaBlogizer - Static Site Publisher
# Supports uhttpd (default) and nginx LXC runtime
# Copyright (C) 2025 CyberMind.fr

CONFIG="metablogizer"
SITES_ROOT="/srv/metablogizer/sites"
NGINX_LXC="metablogizer-nginx"
LXC_PATH="/srv/lxc"
PORT_BASE=8900

. /lib/functions.sh

log_info() { echo "[INFO] $*"; logger -t metablogizer "$*"; }
log_warn() { echo "[WARN] $*" >&2; }
log_error() { echo "[ERROR] $*" >&2; }

uci_get() { uci -q get ${CONFIG}.$1; }
uci_set() { uci set ${CONFIG}.$1="$2" && uci commit ${CONFIG}; }

fix_permissions() {
	local dir="$1"
	[ -d "$dir" ] || return 1
	chmod 755 "$dir"
	find "$dir" -type d -exec chmod 755 {} \;
	find "$dir" -type f -exec chmod 644 {} \;
}

usage() {
	cat <<'EOF'
MetaBlogizer - Static Site Publisher

Usage: metablogizerctl <command> [options]

Site Commands:
  list                  List all sites
  create <name> <domain> [repo]  Create new site
  delete <name>         Delete site
  sync <name>           Sync site from git repo
  publish <name>        Publish site (create HAProxy vhost)
  gitea push <name>     Create Gitea repo and push site content
  gitea init-all        Initialize Gitea repos for all existing sites
  emancipate <name>     KISS ULTIME MODE - Full exposure workflow:
                        1. DNS A record (Gandi/OVH)
                        2. Vortex DNS mesh publication
                        3. HAProxy vhost with SSL
                        4. ACME certificate
                        5. Zero-downtime reload

Runtime Commands:
  runtime               Show current runtime
  runtime set <uhttpd|nginx>  Set runtime preference

Management:
  status                Show overall status
  install-nginx         Install nginx LXC container (optional)

Runtime Selection:
  auto    - Auto-detect (uhttpd preferred)
  uhttpd  - Use uhttpd instances (lightweight)
  nginx   - Use nginx LXC container (more features)

Examples:
  metablogizerctl create myblog blog.example.com
  metablogizerctl emancipate myblog   # Full exposure in one command
EOF
}

# ===========================================
# Runtime Detection
# ===========================================

has_uhttpd() { [ -x /etc/init.d/uhttpd ]; }

has_nginx_lxc() {
	command -v lxc-info >/dev/null 2>&1 && \
	[ -d "$LXC_PATH/$NGINX_LXC/rootfs" ]
}

detect_runtime() {
	local configured=$(uci_get main.runtime)

	case "$configured" in
		uhttpd)
			if has_uhttpd; then
				echo "uhttpd"
			else
				log_error "uhttpd requested but not available"
				return 1
			fi
			;;
		nginx)
			if has_nginx_lxc; then
				echo "nginx"
			else
				log_error "nginx LXC requested but not installed"
				return 1
			fi
			;;
		auto|*)
			# Prefer uhttpd (lighter), fall back to nginx
			if has_uhttpd; then
				echo "uhttpd"
			elif has_nginx_lxc; then
				echo "nginx"
			else
				log_error "No runtime available"
				return 1
			fi
			;;
	esac
}

# ===========================================
# Site Management
# ===========================================

get_next_port() {
	local port=$PORT_BASE
	while uci show uhttpd 2>/dev/null | grep -q "listen_http='0.0.0.0:$port'"; do
		port=$((port + 1))
	done
	echo $port
}

# Convert site name to UCI section name (hyphens -> underscores)
get_section() {
	echo "site_$(echo "$1" | tr '-' '_')"
}

site_exists() {
	local name="$1"
	local section=$(get_section "$name")
	uci -q get ${CONFIG}.${section} >/dev/null 2>&1
}

cmd_list() {
	echo "MetaBlogizer Sites:"
	echo "==================="

	local runtime=$(detect_runtime 2>/dev/null)
	echo "Runtime: ${runtime:-none}"
	echo ""

	config_load "$CONFIG"

	local found=0
	_print_site() {
		local section="$1"
		local name domain port enabled gitea_repo

		config_get name "$section" name
		config_get domain "$section" domain
		config_get port "$section" port
		config_get enabled "$section" enabled "0"
		config_get gitea_repo "$section" gitea_repo ""

		[ -z "$name" ] && return

		local status="disabled"
		[ "$enabled" = "1" ] && status="enabled"

		local dir_status="missing"
		[ -d "$SITES_ROOT/$name" ] && dir_status="exists"

		printf "  %-15s %-25s :%-5s [%s] %s\n" "$name" "$domain" "$port" "$status" "$dir_status"
		found=1
	}
	config_foreach _print_site site

	[ "$found" = "0" ] && echo "  No sites configured"
}

cmd_create() {
	local name="$1"
	local domain="$2"
	local gitea_repo="$3"

	[ -z "$name" ] && { log_error "Site name required"; return 1; }
	[ -z "$domain" ] && { log_error "Domain required"; return 1; }

	# Sanitize name
	name=$(echo "$name" | tr -cd 'a-z0-9_-')

	if site_exists "$name"; then
		log_error "Site '$name' already exists"
		return 1
	fi

	local runtime=$(detect_runtime) || return 1
	local port=$(get_next_port)

	log_info "Creating site: $name ($domain) on port $port using $runtime"

	# Create site directory with proper permissions
	mkdir -p "$SITES_ROOT/$name"
	chmod 755 "$SITES_ROOT/$name"

	# Create placeholder index
	cat > "$SITES_ROOT/$name/index.html" <<EOF
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$name</title>
    <meta property="og:title" content="$name">
    <meta property="og:url" content="https://$domain">
    <meta property="og:type" content="website">
    <style>
        body { font-family: system-ui; max-width: 800px; margin: 50px auto; padding: 20px; }
        h1 { color: #3b82f6; }
    </style>
</head>
<body>
    <h1>$name</h1>
    <p>Site published with MetaBlogizer</p>
    <p><a href="https://$domain">https://$domain</a></p>
</body>
</html>
EOF
	chmod 644 "$SITES_ROOT/$name/index.html"

	# Clone from Gitea if repo specified
	if [ -n "$gitea_repo" ]; then
		local gitea_url=$(uci_get main.gitea_url)
		[ -z "$gitea_url" ] && gitea_url="http://localhost:3000"

		log_info "Cloning from $gitea_url/$gitea_repo..."
		rm -rf "$SITES_ROOT/$name"
		git clone "$gitea_url/$gitea_repo.git" "$SITES_ROOT/$name" 2>/dev/null || {
			log_warn "Git clone failed, using placeholder"
			mkdir -p "$SITES_ROOT/$name"
		}
	fi

	# Always fix permissions for web serving
	fix_permissions "$SITES_ROOT/$name"

	# Configure runtime
	case "$runtime" in
		uhttpd)
			_create_uhttpd_site "$name" "$port"
			;;
		nginx)
			_create_nginx_site "$name"
			;;
	esac

	# Save site config
	uci set ${CONFIG}.site_${name}=site
	uci set ${CONFIG}.site_${name}.name="$name"
	uci set ${CONFIG}.site_${name}.domain="$domain"
	uci set ${CONFIG}.site_${name}.port="$port"
	uci set ${CONFIG}.site_${name}.runtime="$runtime"
	[ -n "$gitea_repo" ] && uci set ${CONFIG}.site_${name}.gitea_repo="$gitea_repo"
	uci set ${CONFIG}.site_${name}.enabled="1"
	uci commit ${CONFIG}

	log_info "Site created: $name"
	log_info "Directory: $SITES_ROOT/$name"
	log_info "Local URL: http://localhost:$port"

	# Auto-push to Gitea if enabled
	local gitea_token_cfg=$(uci_get main.gitea_token)
	if [ -n "$gitea_token_cfg" ]; then
		log_info "Auto-pushing to Gitea..."
		cmd_gitea_push "$name"
	fi

	echo ""
	echo "Next: Run 'metablogizerctl publish $name' to create HAProxy vhost"
}

_create_uhttpd_site() {
	local name="$1"
	local port="$2"

	log_info "Creating uhttpd instance for $name on port $port"

	uci set uhttpd.metablog_${name}=uhttpd
	uci set uhttpd.metablog_${name}.listen_http="0.0.0.0:$port"
	uci set uhttpd.metablog_${name}.home="$SITES_ROOT/$name"
	uci set uhttpd.metablog_${name}.index_page="index.html"
	uci set uhttpd.metablog_${name}.error_page="/index.html"
	uci commit uhttpd

	/etc/init.d/uhttpd reload 2>/dev/null || /etc/init.d/uhttpd restart
}

_create_nginx_site() {
	local name="$1"

	if ! has_nginx_lxc; then
		log_error "nginx LXC not installed. Run: metablogizerctl install-nginx"
		return 1
	fi

	log_info "Creating nginx config for $name"

	local nginx_conf="$LXC_PATH/$NGINX_LXC/rootfs/etc/nginx/sites.d"
	mkdir -p "$nginx_conf"

	cat > "$nginx_conf/metablog-$name.conf" <<EOF
location /$name/ {
    alias /srv/sites/$name/;
    index index.html;
    try_files \$uri \$uri/ /index.html;
}
EOF

	# Reload nginx in container
	lxc-attach -n "$NGINX_LXC" -- nginx -s reload 2>/dev/null || true
}

cmd_publish() {
	local name="$1"
	[ -z "$name" ] && { log_error "Site name required"; return 1; }

	if ! site_exists "$name"; then
		log_error "Site '$name' not found"
		return 1
	fi

	local domain=$(uci_get site_${name}.domain)
	local port=$(uci_get site_${name}.port)

	[ -z "$domain" ] && { log_error "Site domain not configured"; return 1; }

	log_info "Publishing $name to $domain"

	# Create HAProxy backend
	local backend_name="metablog_${name}"
	uci set haproxy.${backend_name}=backend
	uci set haproxy.${backend_name}.name="$backend_name"
	uci set haproxy.${backend_name}.mode="http"
	uci set haproxy.${backend_name}.balance="roundrobin"
	uci set haproxy.${backend_name}.enabled="1"

	# Create HAProxy server
	local server_name="${backend_name}_srv"
	uci set haproxy.${server_name}=server
	uci set haproxy.${server_name}.backend="$backend_name"
	uci set haproxy.${server_name}.name="uhttpd"
	uci set haproxy.${server_name}.address="192.168.255.1"
	uci set haproxy.${server_name}.port="$port"
	uci set haproxy.${server_name}.weight="100"
	uci set haproxy.${server_name}.check="1"
	uci set haproxy.${server_name}.enabled="1"

	# Create HAProxy 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="$backend_name"
	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

	# Regenerate HAProxy config
	/usr/sbin/haproxyctl generate 2>/dev/null
	/etc/init.d/haproxy reload 2>/dev/null

	log_info "Site published!"
	echo ""
	echo "URL: https://$domain"
	echo ""
	echo "To request SSL certificate:"
	echo "  haproxyctl cert add $domain"

	# Auto-package for P2P distribution
	if [ -x /usr/sbin/secubox-content-pkg ]; then
		log_info "Packaging site for P2P distribution..."
		/usr/sbin/secubox-content-pkg site "$name" "$domain" 2>/dev/null && \
			log_info "Site packaged for mesh distribution"
	fi
}

cmd_delete() {
	local name="$1"
	[ -z "$name" ] && { log_error "Site name required"; return 1; }

	log_info "Deleting site: $name"

	# Remove uhttpd instance
	uci delete uhttpd.metablog_${name} 2>/dev/null
	uci commit uhttpd
	/etc/init.d/uhttpd reload 2>/dev/null

	# Remove HAProxy config
	local domain=$(uci_get site_${name}.domain)
	if [ -n "$domain" ]; then
		local vhost_name=$(echo "$domain" | tr '.-' '_')
		uci delete haproxy.${vhost_name} 2>/dev/null
		uci delete haproxy.metablog_${name} 2>/dev/null
		uci delete haproxy.metablog_${name}_srv 2>/dev/null
		uci commit haproxy
		/usr/sbin/haproxyctl generate 2>/dev/null
		/etc/init.d/haproxy reload 2>/dev/null
	fi

	# Remove site config
	uci delete ${CONFIG}.site_${name} 2>/dev/null
	uci commit ${CONFIG}

	# Optionally remove files
	if [ -d "$SITES_ROOT/$name" ]; then
		echo "Site directory: $SITES_ROOT/$name"
		echo "Remove manually if desired: rm -rf $SITES_ROOT/$name"
	fi

	log_info "Site deleted"
}

cmd_sync() {
	local name="$1"
	[ -z "$name" ] && { log_error "Site name required"; return 1; }

	local section=$(get_section "$name")
	local gitea_repo=$(uci_get ${section}.gitea_repo)
	[ -z "$gitea_repo" ] && { log_error "No git repo configured for $name"; return 1; }

	local site_dir="$SITES_ROOT/$name"
	[ ! -d "$site_dir" ] && { log_error "Site directory not found"; return 1; }

	log_info "Syncing $name from git..."

	cd "$site_dir"
	if [ -d ".git" ]; then
		git pull origin main 2>/dev/null || git pull origin master 2>/dev/null || git pull
	else
		local gitea_url=$(uci_get main.gitea_url)
		[ -z "$gitea_url" ] && gitea_url="http://localhost:3000"
		git clone "$gitea_url/$gitea_repo.git" /tmp/metablog-sync-$$
		cp -r /tmp/metablog-sync-$$/* "$site_dir/"
		rm -rf /tmp/metablog-sync-$$
	fi

	# Fix permissions for web serving
	fix_permissions "$site_dir"

	log_info "Sync complete"
}

# Create Gitea repo via API and push local site content
cmd_gitea_push() {
	local name="$1"
	[ -z "$name" ] && { log_error "Site name required"; return 1; }

	if ! site_exists "$name"; then
		log_error "Site '$name' not found"
		return 1
	fi

	# Load Gitea config from dedicated gitea section
	local gitea_enabled=$(uci_get gitea.enabled)
	local gitea_url=$(uci_get gitea.url)
	local gitea_user=$(uci_get gitea.user)
	local gitea_token=$(uci_get gitea.token)

	[ -z "$gitea_url" ] && gitea_url="http://localhost:3000"

	if [ -z "$gitea_token" ]; then
		log_error "Gitea token not configured"
		log_info "Configure with:"
		log_info "  uci set metablogizer.gitea=gitea"
		log_info "  uci set metablogizer.gitea.enabled=1"
		log_info "  uci set metablogizer.gitea.url='http://192.168.255.1:3001'"
		log_info "  uci set metablogizer.gitea.user='admin'"
		log_info "  uci set metablogizer.gitea.token='your-token'"
		log_info "  uci commit metablogizer"
		return 1
	fi

	local site_dir="$SITES_ROOT/$name"

	if [ ! -d "$site_dir" ]; then
		log_error "Site '$name' not found at $site_dir"
		return 1
	fi

	local gitea_host=$(echo "$gitea_url" | sed 's|^https\?://||' | sed 's|/.*||')
	local gitea_proto=$(echo "$gitea_url" | grep -q '^https' && echo "https" || echo "http")
	local repo_name="metablog-$name"

	log_info "Creating Gitea repository: $repo_name"

	# Check if repo exists, create if not
	local repo_check=$(curl -s -o /dev/null -w "%{http_code}" \
		-H "Authorization: token $gitea_token" \
		"${gitea_url}/api/v1/repos/${gitea_user}/${repo_name}" 2>/dev/null)

	if [ "$repo_check" != "200" ]; then
		log_info "Repository doesn't exist, creating..."
		local create_result=$(curl -s -X POST \
			-H "Authorization: token $gitea_token" \
			-H "Content-Type: application/json" \
			-d "{\"name\":\"${repo_name}\",\"description\":\"MetaBlogizer site: ${name}\",\"private\":true,\"auto_init\":false}" \
			"${gitea_url}/api/v1/user/repos" 2>/dev/null)

		if ! echo "$create_result" | grep -q "\"name\":"; then
			log_error "Failed to create repository"
			log_error "Response: $create_result"
			return 1
		fi
		log_info "Repository created: ${gitea_user}/${repo_name}"
	else
		log_info "Repository exists: ${gitea_user}/${repo_name}"
	fi

	# Initialize git in site directory if needed
	cd "$site_dir"

	if [ ! -d ".git" ]; then
		log_info "Initializing git repository..."
		git init
		git config user.name "$gitea_user"
		git config user.email "${gitea_user}@localhost"
	fi

	# Set remote
	local remote_url="${gitea_proto}://${gitea_user}:${gitea_token}@${gitea_host}/${gitea_user}/${repo_name}.git"
	git remote remove origin 2>/dev/null
	git remote add origin "$remote_url"

	# Add, commit and push
	log_info "Adding files and committing..."
	git add -A
	git commit -m "Auto-push from SecuBox MetaBlogizer at $(date -Iseconds)" 2>/dev/null || \
		log_info "No changes to commit"

	log_info "Pushing to Gitea..."
	git push -u origin HEAD:main --force 2>&1 || {
		# Try master branch as fallback
		git push -u origin HEAD:master --force 2>&1 || {
			log_error "Failed to push to Gitea"
			return 1
		}
	}

	# Save repo reference in UCI
	local section=$(get_section "$name")
	uci set "${CONFIG}.${section}.gitea_repo=${gitea_user}/${repo_name}"
	uci set "${CONFIG}.${section}.gitea_synced=$(date -Iseconds)"
	uci commit "$CONFIG"

	log_info "Push complete: ${gitea_url}/${gitea_user}/${repo_name}"
}

# Initialize Gitea for all existing sites
cmd_gitea_init_all() {
	local gitea_token=$(uci_get main.gitea_token)

	if [ -z "$gitea_token" ]; then
		log_error "Gitea token not configured"
		log_info "Configure with:"
		log_info "  uci set metablogizer.main.gitea_url='http://192.168.255.1:3000'"
		log_info "  uci set metablogizer.main.gitea_user='admin'"
		log_info "  uci set metablogizer.main.gitea_token='your-token'"
		log_info "  uci commit metablogizer"
		return 1
	fi

	log_info "Initializing Gitea repositories for all sites..."
	echo ""

	local success=0
	local failed=0

	# Load config and iterate over sites
	config_load "$CONFIG"

	_init_site_gitea() {
		local section="$1"
		local name
		config_get name "$section" name

		[ -z "$name" ] && return

		# Check if site directory exists
		if [ ! -d "$SITES_ROOT/$name" ]; then
			log_warn "[$name] Site directory not found, skipping"
			return
		fi

		# Check if already has a repo configured
		local existing_repo
		config_get existing_repo "$section" gitea_repo

		if [ -n "$existing_repo" ]; then
			log_info "[$name] Already linked to $existing_repo, syncing..."
		else
			log_info "[$name] Creating Gitea repository..."
		fi

		if cmd_gitea_push "$name"; then
			success=$((success + 1))
		else
			failed=$((failed + 1))
		fi
		echo ""
	}

	config_foreach _init_site_gitea site

	echo "========================================"
	echo "Gitea initialization complete"
	echo "  Success: $success"
	echo "  Failed:  $failed"
	echo "========================================"
}

cmd_runtime() {
	local action="$1"
	local value="$2"

	if [ "$action" = "set" ]; then
		case "$value" in
			uhttpd|nginx|auto)
				uci_set main.runtime "$value"
				log_info "Runtime set to: $value"
				;;
			*)
				log_error "Invalid runtime: $value (use uhttpd, nginx, or auto)"
				return 1
				;;
		esac
	else
		local configured=$(uci_get main.runtime)
		local detected=$(detect_runtime 2>/dev/null)
		echo "Configured: ${configured:-auto}"
		echo "Detected:   ${detected:-none}"
		echo ""
		echo "Available:"
		has_uhttpd && echo "  - uhttpd (installed)" || echo "  - uhttpd (not available)"
		has_nginx_lxc && echo "  - nginx LXC (installed)" || echo "  - nginx LXC (not installed)"
	fi
}

cmd_status() {
	echo "MetaBlogizer Status"
	echo "==================="

	local enabled=$(uci_get main.enabled)
	local runtime=$(detect_runtime 2>/dev/null)
	local sites_count=$(uci show $CONFIG 2>/dev/null | grep -c "=site")

	echo "Enabled:    $([ "$enabled" = "1" ] && echo "yes" || echo "no")"
	echo "Runtime:    ${runtime:-none}"
	echo "Sites:      $sites_count"
	echo "Sites Root: $SITES_ROOT"
	echo ""

	cmd_list
}

cmd_install_nginx() {
	log_info "Installing nginx LXC container..."

	command -v lxc-start >/dev/null 2>&1 || {
		log_error "LXC not installed. Install with: opkg install lxc lxc-common"
		return 1
	}

	local rootfs="$LXC_PATH/$NGINX_LXC/rootfs"
	mkdir -p "$LXC_PATH/$NGINX_LXC"

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

	log_info "Downloading Alpine Linux..."
	wget -q -O /tmp/alpine-nginx.tar.gz \
		"https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/$arch/alpine-minirootfs-3.19.0-$arch.tar.gz" || {
		log_error "Failed to download Alpine"
		return 1
	}

	mkdir -p "$rootfs"
	tar xzf /tmp/alpine-nginx.tar.gz -C "$rootfs"
	rm -f /tmp/alpine-nginx.tar.gz

	# Configure
	echo "nameserver 8.8.8.8" > "$rootfs/etc/resolv.conf"

	# Install nginx
	chroot "$rootfs" /bin/sh -c "apk update && apk add --no-cache nginx"

	# Create LXC config
	cat > "$LXC_PATH/$NGINX_LXC/config" <<EOF
lxc.uts.name = $NGINX_LXC
lxc.rootfs.path = dir:$rootfs
lxc.net.0.type = none
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.mount.entry = $SITES_ROOT srv/sites none bind,create=dir 0 0
lxc.cap.drop = sys_admin sys_module mac_admin mac_override
lxc.init.cmd = /usr/sbin/nginx -g 'daemon off;'
EOF

	log_info "nginx LXC installed"
	log_info "Start with: lxc-start -n $NGINX_LXC -d"
}

# ===========================================
# KISS ULTIME MODE - Emancipate
# ===========================================

_emancipate_dns() {
	local name="$1"
	local domain="$2"
	local default_zone=$(uci -q get dns-provider.main.zone)
	local provider=$(uci -q get dns-provider.main.provider)
	local vortex_wildcard=$(uci -q get vortex-dns.master.wildcard_domain)

	# Check if dnsctl is available
	if ! command -v dnsctl >/dev/null 2>&1; then
		log_warn "[DNS] dnsctl not found, skipping external DNS"
		return 1
	fi

	# Get public IP
	local public_ip=$(curl -s --connect-timeout 5 https://ipv4.icanhazip.com 2>/dev/null | tr -d '\n')
	[ -z "$public_ip" ] && { log_warn "[DNS] Cannot detect public IP, skipping DNS"; return 1; }

	# Detect zone from domain suffix (try known zones)
	local zone=""
	local subdomain=""
	for z in "secubox.in" "maegia.tv" "cybermind.fr"; do
		if echo "$domain" | grep -q "\.${z}$"; then
			zone="$z"
			subdomain=$(echo "$domain" | sed "s/\.${z}$//")
			break
		elif [ "$domain" = "$z" ]; then
			zone="$z"
			subdomain="@"
			break
		fi
	done

	# Fallback to default zone if no match
	if [ -z "$zone" ]; then
		zone="$default_zone"
		subdomain=$(echo "$domain" | sed "s/\.${zone}$//")
	fi

	[ -z "$zone" ] && { log_warn "[DNS] No zone detected, skipping external DNS"; return 1; }

	log_info "[DNS] Registering $subdomain.$zone -> $public_ip via $provider"

	# Register on the published domain's zone
	dnsctl -z "$zone" add A "$subdomain" "$public_ip" 3600

	# Also register on vortex node subdomain (e.g., bday.gk2.secubox.in)
	if [ -n "$vortex_wildcard" ]; then
		local vortex_zone=$(echo "$vortex_wildcard" | sed 's/^[^.]*\.//')
		local vortex_node=$(echo "$vortex_wildcard" | cut -d. -f1)
		local vortex_subdomain="${name}.${vortex_node}"
		log_info "[DNS] Registering $vortex_subdomain.$vortex_zone -> $public_ip (vortex node)"
		dnsctl -z "$vortex_zone" add A "$vortex_subdomain" "$public_ip" 3600
	fi

	log_info "[DNS] Verify with: dnsctl verify $domain"
}

_emancipate_vortex() {
	local name="$1"
	local domain="$2"

	# Check if vortexctl is available
	if ! command -v vortexctl >/dev/null 2>&1; then
		log_info "[VORTEX] vortexctl not found, skipping mesh publication"
		return 0
	fi

	# Check if vortex-dns is enabled
	local vortex_enabled=$(uci -q get vortex-dns.main.enabled)

	if [ "$vortex_enabled" = "1" ]; then
		log_info "[VORTEX] Publishing $name as $domain to mesh"
		vortexctl mesh publish "$name" "$domain" 2>/dev/null
	else
		log_info "[VORTEX] Vortex DNS disabled, skipping mesh publication"
	fi
}

_emancipate_haproxy() {
	local name="$1"
	local domain="$2"
	local port=$(uci_get site_${name}.port)

	log_info "[HAPROXY] Creating vhost for $domain"

	# Create backend
	local backend_name="metablog_${name}"
	uci set haproxy.${backend_name}=backend
	uci set haproxy.${backend_name}.name="$backend_name"
	uci set haproxy.${backend_name}.mode="http"
	uci set haproxy.${backend_name}.balance="roundrobin"
	uci set haproxy.${backend_name}.enabled="1"

	# Create server
	local server_name="${backend_name}_srv"
	uci set haproxy.${server_name}=server
	uci set haproxy.${server_name}.backend="$backend_name"
	uci set haproxy.${server_name}.name="uhttpd"
	uci set haproxy.${server_name}.address="192.168.255.1"
	uci set haproxy.${server_name}.port="$port"
	uci set haproxy.${server_name}.weight="100"
	uci set haproxy.${server_name}.check="1"
	uci set haproxy.${server_name}.enabled="1"

	# Create vhost with SSL
	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="$backend_name"
	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

	# Generate HAProxy config
	if command -v haproxyctl >/dev/null 2>&1; then
		haproxyctl generate 2>/dev/null
	fi
}

_emancipate_ssl() {
	local domain="$1"

	log_info "[SSL] Requesting certificate for $domain"

	# Check if haproxyctl is available
	if ! command -v haproxyctl >/dev/null 2>&1; then
		log_warn "[SSL] haproxyctl not found, skipping SSL"
		return 1
	fi

	# haproxyctl cert add handles ACME webroot mode (no HAProxy restart needed)
	haproxyctl cert add "$domain" 2>&1 | while read line; do
		echo "  $line"
	done

	if [ -f "/srv/haproxy/certs/$domain.pem" ]; then
		log_info "[SSL] Certificate obtained successfully"
	else
		log_warn "[SSL] Certificate request may still be pending"
		log_warn "[SSL] Check with: haproxyctl cert verify $domain"
	fi
}

_emancipate_reload() {
	log_info "[RELOAD] Applying HAProxy configuration"
	# Generate fresh config
	haproxyctl generate 2>/dev/null
	# Always restart for clean state with new vhosts/certs
	log_info "[RELOAD] Restarting HAProxy for clean state..."
	/etc/init.d/haproxy restart 2>/dev/null
	sleep 1
	# Verify HAProxy is running
	if pgrep haproxy >/dev/null 2>&1; then
		log_info "[RELOAD] HAProxy restarted successfully"
	else
		log_warn "[RELOAD] HAProxy may not have started properly"
	fi
}

cmd_emancipate() {
	local name="$1"
	[ -z "$name" ] && { log_error "Site name required"; usage; return 1; }

	if ! site_exists "$name"; then
		log_error "Site '$name' not found"
		log_error "Create first: metablogizerctl create $name <domain>"
		return 1
	fi

	local section=$(get_section "$name")
	local domain=$(uci_get ${section}.domain)
	[ -z "$domain" ] && { log_error "Site domain not configured"; return 1; }

	echo ""
	echo "=============================================="
	echo "  KISS ULTIME MODE: Emancipating $name"
	echo "=============================================="
	echo ""

	# Step 1: DNS Registration (external provider)
	_emancipate_dns "$name" "$domain"

	# Step 2: Vortex DNS (mesh registration)
	_emancipate_vortex "$name" "$domain"

	# Step 3: HAProxy vhost + backend
	_emancipate_haproxy "$name" "$domain"

	# Step 4: SSL Certificate
	_emancipate_ssl "$domain"

	# Step 5: Reload HAProxy
	_emancipate_reload

	# Mark site as emancipated
	uci set ${CONFIG}.${section}.emancipated="1"
	uci set ${CONFIG}.${section}.emancipated_at="$(date -Iseconds)"
	uci commit ${CONFIG}

	echo ""
	echo "=============================================="
	echo "  EMANCIPATION COMPLETE"
	echo "=============================================="
	echo ""
	echo "  Site:    https://$domain"
	echo "  Status:  Published and SSL-protected"
	echo "  Mesh:    $(uci -q get vortex-dns.main.enabled | grep -q 1 && echo 'Published' || echo 'Disabled')"
	echo ""
	echo "  Verify:"
	echo "    curl -v https://$domain"
	echo "    dnsctl verify $domain"
	echo "    haproxyctl cert verify $domain"
	echo ""
}

# ===========================================
# Main
# ===========================================

case "${1:-}" in
	list)           shift; cmd_list "$@" ;;
	create)         shift; cmd_create "$@" ;;
	delete)         shift; cmd_delete "$@" ;;
	sync)           shift; cmd_sync "$@" ;;
	publish)        shift; cmd_publish "$@" ;;
	emancipate)     shift; cmd_emancipate "$@" ;;
	runtime)        shift; cmd_runtime "$@" ;;
	status)         shift; cmd_status "$@" ;;
	install-nginx)  shift; cmd_install_nginx "$@" ;;
	gitea)
		shift
		case "${1:-}" in
			push)     shift; cmd_gitea_push "$@" ;;
			init-all) shift; cmd_gitea_init_all "$@" ;;
			*)        echo "Usage: metablogizerctl gitea {push|init-all} [name]"; exit 1 ;;
		esac
		;;
	help|--help|-h) usage ;;
	*)              usage ;;
esac
