#!/bin/sh
# SecuBox Subdomain Generator
# Creates DNS + HAProxy + SSL configuration for new subdomains
# Uses wildcard certificate for *.zone

VERSION="1.0.0"
CONFIG="dns-provider"
HAPROXY_VHOSTS="/etc/haproxy/conf.d"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

log() { echo -e "${GREEN}[SUBDOMAIN]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }

uci_get() { uci -q get ${CONFIG}.$1; }
get_zone() { uci_get main.zone; }
get_public_ip() {
	curl -s --connect-timeout 5 https://ipv4.icanhazip.com 2>/dev/null | tr -d '\n'
}

# ============================================================================
# Add Subdomain
# ============================================================================

cmd_add() {
	local name="$1"
	local backend_port="$2"
	local description="${3:-}"

	if [ -z "$name" ] || [ -z "$backend_port" ]; then
		echo "Usage: secubox-subdomain add <name> <backend_port> [description]"
		echo ""
		echo "Examples:"
		echo "  secubox-subdomain add api 8080 'API Gateway'"
		echo "  secubox-subdomain add grafana 3000 'Monitoring Dashboard'"
		return 1
	fi

	local zone=$(get_zone)
	if [ -z "$zone" ]; then
		error "No DNS zone configured. Run: uci set dns-provider.main.zone='example.com'"
		return 1
	fi

	local fqdn="${name}.${zone}"
	local public_ip=$(get_public_ip)

	if [ -z "$public_ip" ]; then
		error "Cannot detect public IP"
		return 1
	fi

	log "Creating subdomain: $fqdn → 127.0.0.1:$backend_port"

	# Step 1: Add DNS A record
	log "  [1/4] Adding DNS A record..."
	dnsctl add A "$name" "$public_ip" 300
	if [ $? -ne 0 ]; then
		error "Failed to add DNS record"
		return 1
	fi

	# Step 2: Create HAProxy vhost config
	log "  [2/4] Creating HAProxy vhost..."
	mkdir -p "$HAPROXY_VHOSTS"

	cat > "${HAPROXY_VHOSTS}/${name}.${zone}.cfg" << EOF
# HAProxy vhost for ${fqdn}
# Generated by secubox-subdomain v${VERSION}
# Backend port: ${backend_port}
# Description: ${description:-Auto-generated subdomain}

acl host_${name//-/_}_${zone//\./_} hdr(host) -i ${fqdn}
use_backend backend_${name//-/_} if host_${name//-/_}_${zone//\./_}

backend backend_${name//-/_}
    mode http
    option httpchk GET /
    server ${name} 127.0.0.1:${backend_port} check inter 10s
EOF

	# Step 3: Register in UCI
	log "  [3/4] Registering in UCI..."
	local idx=$(uci show haproxy 2>/dev/null | grep -c "=vhost")
	uci set haproxy.vhost_${name}=vhost
	uci set haproxy.vhost_${name}.enabled='1'
	uci set haproxy.vhost_${name}.domain="$fqdn"
	uci set haproxy.vhost_${name}.backend_port="$backend_port"
	uci set haproxy.vhost_${name}.description="${description:-}"
	uci set haproxy.vhost_${name}.created="$(date -Iseconds)"
	uci commit haproxy

	# Step 4: Reload HAProxy
	log "  [4/4] Reloading HAProxy..."
	if command -v haproxyctl >/dev/null 2>&1; then
		haproxyctl reload 2>/dev/null || true
	fi

	echo ""
	log "Subdomain created: https://${fqdn}"
	log "Using wildcard cert: *.${zone}"
	log ""
	log "Verify DNS: dnsctl verify ${fqdn}"
}

# ============================================================================
# List Subdomains
# ============================================================================

cmd_list() {
	local zone=$(get_zone)

	echo ""
	echo "=========================================="
	echo "  SecuBox Subdomains"
	echo "=========================================="
	echo ""
	echo "Zone: ${zone:-not configured}"
	echo ""

	if [ -z "$zone" ]; then
		warn "No zone configured"
		return 0
	fi

	# List from UCI
	printf "%-20s %-8s %-10s %s\n" "SUBDOMAIN" "PORT" "STATUS" "DESCRIPTION"
	printf "%-20s %-8s %-10s %s\n" "---------" "----" "------" "-----------"

	local count=0
	for section in $(uci show haproxy 2>/dev/null | grep "=vhost$" | cut -d. -f2 | cut -d= -f1); do
		local enabled=$(uci -q get haproxy.${section}.enabled)
		local domain=$(uci -q get haproxy.${section}.domain)
		local port=$(uci -q get haproxy.${section}.backend_port)
		local desc=$(uci -q get haproxy.${section}.description)

		if [ -n "$domain" ]; then
			local name=$(echo "$domain" | sed "s/\.${zone}$//")
			local status="active"
			[ "$enabled" != "1" ] && status="disabled"

			printf "%-20s %-8s %-10s %s\n" "$name" "${port:-?}" "$status" "${desc:-}"
			count=$((count + 1))
		fi
	done

	if [ "$count" -eq 0 ]; then
		echo "  No subdomains configured"
	fi
	echo ""
	echo "Total: $count subdomain(s)"
	echo ""
}

# ============================================================================
# Remove Subdomain
# ============================================================================

cmd_remove() {
	local name="$1"

	if [ -z "$name" ]; then
		echo "Usage: secubox-subdomain remove <name>"
		return 1
	fi

	local zone=$(get_zone)
	local fqdn="${name}.${zone}"

	log "Removing subdomain: $fqdn"

	# Step 1: Remove DNS record
	log "  [1/3] Removing DNS A record..."
	dnsctl rm A "$name" 2>/dev/null || true

	# Step 2: Remove HAProxy vhost config
	log "  [2/3] Removing HAProxy vhost..."
	rm -f "${HAPROXY_VHOSTS}/${name}.${zone}.cfg"

	# Step 3: Remove UCI entry
	log "  [3/3] Removing UCI entry..."
	uci delete haproxy.vhost_${name} 2>/dev/null || true
	uci commit haproxy

	# Reload HAProxy
	if command -v haproxyctl >/dev/null 2>&1; then
		haproxyctl reload 2>/dev/null || true
	fi

	log "Subdomain removed: $fqdn"
}

# ============================================================================
# Enable/Disable
# ============================================================================

cmd_enable() {
	local name="$1"
	[ -z "$name" ] && { echo "Usage: secubox-subdomain enable <name>"; return 1; }

	uci set haproxy.vhost_${name}.enabled='1'
	uci commit haproxy
	log "Enabled: $name"
}

cmd_disable() {
	local name="$1"
	[ -z "$name" ] && { echo "Usage: secubox-subdomain disable <name>"; return 1; }

	uci set haproxy.vhost_${name}.enabled='0'
	uci commit haproxy
	log "Disabled: $name"
}

# ============================================================================
# Sync - Import existing HAProxy vhosts
# ============================================================================

cmd_sync() {
	local zone=$(get_zone)
	log "Syncing HAProxy vhosts from ${HAPROXY_VHOSTS}..."

	local count=0
	ls ${HAPROXY_VHOSTS}/*.cfg >/dev/null 2>&1 || { log "No vhost configs found"; return 0; }
	for cfg in ${HAPROXY_VHOSTS}/*.cfg; do
		[ -f "$cfg" ] || continue
		local filename=$(basename "$cfg" .cfg)

		# Check if it matches our zone
		if echo "$filename" | grep -q "\.${zone}$"; then
			local name=$(echo "$filename" | sed "s/\.${zone}$//")
			local port=$(grep "server.*127.0.0.1:" "$cfg" 2>/dev/null | head -1 | sed 's/.*127.0.0.1:\([0-9]*\).*/\1/')

			if [ -n "$name" ] && [ -n "$port" ]; then
				# Register if not already in UCI
				if ! uci -q get haproxy.vhost_${name} >/dev/null 2>&1; then
					log "  Importing: $name (port $port)"
					uci set haproxy.vhost_${name}=vhost
					uci set haproxy.vhost_${name}.enabled='1'
					uci set haproxy.vhost_${name}.domain="${name}.${zone}"
					uci set haproxy.vhost_${name}.backend_port="$port"
					uci set haproxy.vhost_${name}.imported='1'
					count=$((count + 1))
				fi
			fi
		fi
	done

	uci commit haproxy
	log "Imported $count vhost(s)"
}

# ============================================================================
# Quick Add - Shorthand for common services
# ============================================================================

cmd_quick() {
	local service="$1"

	case "$service" in
		gitea)     cmd_add gitea 3000 "Gitea Git Server" ;;
		grafana)   cmd_add grafana 3000 "Grafana Monitoring" ;;
		portainer) cmd_add portainer 9000 "Portainer Docker UI" ;;
		jellyfin)  cmd_add jellyfin 8096 "Jellyfin Media Server" ;;
		nextcloud) cmd_add nextcloud 8080 "Nextcloud Cloud Storage" ;;
		homeassistant|ha) cmd_add ha 8123 "Home Assistant" ;;
		*)
			echo "Quick service shortcuts:"
			echo "  secubox-subdomain quick gitea"
			echo "  secubox-subdomain quick grafana"
			echo "  secubox-subdomain quick portainer"
			echo "  secubox-subdomain quick jellyfin"
			echo "  secubox-subdomain quick nextcloud"
			echo "  secubox-subdomain quick ha"
			;;
	esac
}

# ============================================================================
# Help
# ============================================================================

show_help() {
	cat << EOF
SecuBox Subdomain Generator v${VERSION}

Usage: secubox-subdomain <command> [options]

Commands:
  add <name> <port> [desc]  Create new subdomain with DNS + HAProxy
  remove <name>             Remove subdomain (DNS + HAProxy + UCI)
  list                      List all configured subdomains
  enable <name>             Enable a subdomain
  disable <name>            Disable a subdomain
  sync                      Import existing HAProxy vhosts to UCI
  quick <service>           Quick-add common services

Examples:
  secubox-subdomain add api 8080 "REST API Gateway"
  secubox-subdomain add dashboard 3000
  secubox-subdomain remove api
  secubox-subdomain list
  secubox-subdomain quick gitea

Notes:
  - Uses wildcard certificate (*.zone) for SSL
  - DNS records added via dnsctl (Gandi/OVH/Cloudflare)
  - HAProxy vhosts auto-generated in ${HAPROXY_VHOSTS}

EOF
}

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

case "${1:-}" in
	add)       shift; cmd_add "$@" ;;
	remove|rm) shift; cmd_remove "$@" ;;
	list|ls)   shift; cmd_list "$@" ;;
	enable)    shift; cmd_enable "$@" ;;
	disable)   shift; cmd_disable "$@" ;;
	sync)      shift; cmd_sync "$@" ;;
	quick)     shift; cmd_quick "$@" ;;
	help|--help|-h|'') show_help ;;
	*)         error "Unknown command: $1"; show_help >&2; exit 1 ;;
esac

exit 0
