#!/bin/sh
# SecuBox Roundcube Webmail Controller
# LXC-based nginx + PHP-FPM + Roundcube

VERSION="1.0.0"
CONFIG="roundcube"
CONTAINER="roundcube"
LXC_PATH="/srv/lxc/roundcube"
ROUNDCUBE_VERSION="1.6.12"

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

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

# ============================================================================
# Configuration
# ============================================================================

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

require_root() {
	[ "$(id -u)" -eq 0 ] || { error "Root required"; exit 1; }
}

defaults() {
	port="$(uci_get main.port)"
	[ -z "$port" ] && port="8027"
	mail_host="$(uci_get main.mail_host)"
	[ -z "$mail_host" ] && mail_host="192.168.255.30"
	domain="$(uci_get main.domain)"
	[ -z "$domain" ] && domain="webmail.gk2.secubox.in"
}

ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }

# ============================================================================
# LXC Helpers
# ============================================================================

lxc_running() {
	lxc-info -n "$CONTAINER" 2>/dev/null | grep -q "State:.*RUNNING"
}

lxc_exists() {
	[ -d "$LXC_PATH/rootfs" ]
}

create_lxc_config() {
	defaults
	cat > "$LXC_PATH/config" << EOF
lxc.uts.name = roundcube
lxc.rootfs.path = dir:${LXC_PATH}/rootfs
lxc.net.0.type = none
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.cap.drop = sys_module mac_admin mac_override sys_time
lxc.seccomp.profile =
lxc.tty.max = 0
lxc.pty.max = 256
lxc.cgroup2.memory.max = 128000000
lxc.init.cmd = /opt/start-roundcube.sh
EOF
}

create_startup_script() {
	cat > "$LXC_PATH/rootfs/opt/start-roundcube.sh" << 'EOF'
#!/bin/sh
set -e

# Initialize SQLite database if not exists
if [ ! -f /var/www/roundcube/db/roundcube.db ]; then
    echo "Initializing Roundcube database..."
    mkdir -p /var/www/roundcube/db
    cd /var/www/roundcube
    sqlite3 db/roundcube.db < SQL/sqlite.initial.sql
    chown nginx:nginx db/roundcube.db
    chmod 640 db/roundcube.db
    echo "Database initialized"
fi

# Start PHP-FPM
echo "Starting PHP-FPM..."
php-fpm84 -D

# Start nginx in foreground
echo "Starting nginx..."
exec nginx -g "daemon off;"
EOF
	chmod +x "$LXC_PATH/rootfs/opt/start-roundcube.sh"
}

# ============================================================================
# Installation
# ============================================================================

bootstrap_alpine() {
	require_root
	log "Bootstrapping Alpine Linux rootfs..."

	ensure_dir "$LXC_PATH"
	cd "$LXC_PATH"

	if [ ! -f sbin/apk.static ]; then
		log "Downloading apk-tools-static..."
		curl -L -o apk-tools-static.apk \
			"https://dl-cdn.alpinelinux.org/alpine/v3.21/main/aarch64/apk-tools-static-2.14.6-r3.apk"
		tar -xzf apk-tools-static.apk sbin/apk.static
		rm -f apk-tools-static.apk
	fi

	log "Installing base system..."
	./sbin/apk.static -X https://dl-cdn.alpinelinux.org/alpine/v3.21/main \
		-U --allow-untrusted --root rootfs --initdb add \
		alpine-base alpine-baselayout busybox musl

	mkdir -p rootfs/etc/apk
	cat > rootfs/etc/apk/repositories << 'EOF'
https://dl-cdn.alpinelinux.org/alpine/v3.21/main
https://dl-cdn.alpinelinux.org/alpine/v3.21/community
EOF

	cat > rootfs/etc/resolv.conf << 'EOF'
nameserver 8.8.8.8
nameserver 1.1.1.1
EOF

	log "Base system installed"
}

install_packages() {
	require_root

	if ! lxc_running; then
		log "Starting container for package installation..."
		lxc-start -n "$CONTAINER" -d
		sleep 3
	fi

	log "Installing packages..."
	lxc-attach -n "$CONTAINER" -- apk update
	lxc-attach -n "$CONTAINER" -- apk add --no-cache \
		nginx \
		php84 php84-fpm php84-imap php84-mbstring php84-openssl \
		php84-session php84-pdo php84-pdo_sqlite php84-sqlite3 \
		php84-xml php84-dom php84-intl php84-zip php84-gd \
		php84-ctype php84-json php84-fileinfo php84-ldap \
		sqlite curl

	log "Packages installed"
}

download_roundcube() {
	local rootfs="$LXC_PATH/rootfs"

	log "Downloading Roundcube $ROUNDCUBE_VERSION..."

	mkdir -p "$rootfs/var/www"
	curl -L -o "$rootfs/tmp/roundcube.tar.gz" \
		"https://github.com/roundcube/roundcubemail/releases/download/${ROUNDCUBE_VERSION}/roundcubemail-${ROUNDCUBE_VERSION}-complete.tar.gz"

	tar -xzf "$rootfs/tmp/roundcube.tar.gz" -C "$rootfs/var/www/"
	mv "$rootfs/var/www/roundcubemail-${ROUNDCUBE_VERSION}" "$rootfs/var/www/roundcube"
	rm -f "$rootfs/tmp/roundcube.tar.gz"

	log "Roundcube downloaded"
}

configure_roundcube() {
	defaults
	local rootfs="$LXC_PATH/rootfs"

	log "Configuring Roundcube..."

	cat > "$rootfs/var/www/roundcube/config/config.inc.php" << EOF
<?php
\$config["db_dsnw"] = "sqlite:////var/www/roundcube/db/roundcube.db?mode=0640";
\$config["imap_host"] = "ssl://${mail_host}:993";
\$config["smtp_host"] = "ssl://${mail_host}:465";
\$config["imap_conn_options"] = [
    "ssl" => ["verify_peer" => false, "verify_peer_name" => false]
];
\$config["smtp_conn_options"] = [
    "ssl" => ["verify_peer" => false, "verify_peer_name" => false]
];
\$config["support_url"] = "";
\$config["product_name"] = "SecuBox Webmail";
\$config["des_key"] = "rcmail-!24ByteDESKey*Sym";
\$config["plugins"] = ["archive", "zipdownload"];
\$config["skin"] = "elastic";
\$config["language"] = "fr_FR";
EOF

	# Configure nginx
	cat > "$rootfs/etc/nginx/http.d/roundcube.conf" << EOF
server {
    listen ${port};
    server_name _;
    root /var/www/roundcube;
    index index.php;

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

    location ~ \.php\$ {
        fastcgi_pass unix:/run/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }

    location ~ /\. {
        deny all;
    }
}
EOF

	# Configure PHP-FPM
	mkdir -p "$rootfs/etc/php84/php-fpm.d"
	cat > "$rootfs/etc/php84/php-fpm.d/www.conf" << 'EOF'
[www]
user = nginx
group = nginx
listen = /run/php-fpm.sock
listen.owner = nginx
listen.group = nginx
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
EOF

	# Set permissions
	lxc-attach -n "$CONTAINER" -- chown -R nginx:nginx /var/www/roundcube 2>/dev/null || true

	log "Roundcube configured"
}

configure_haproxy() {
	defaults

	if ! command -v haproxyctl >/dev/null 2>&1; then
		warn "haproxyctl not found"
		return 0
	fi

	local vhost_name=$(echo "$domain" | tr '.' '_')

	if ! uci -q get haproxy.roundcube >/dev/null 2>&1; then
		log "Creating HAProxy backend..."
		uci set haproxy.roundcube=backend
		uci set haproxy.roundcube.name='roundcube'
		uci set haproxy.roundcube.mode='http'
		uci set haproxy.roundcube.balance='roundrobin'
		uci set haproxy.roundcube.enabled='1'
		uci set haproxy.roundcube.option='forwardfor'
		uci add_list haproxy.roundcube.http_request='set-header X-Forwarded-Proto https'
		uci add_list haproxy.roundcube.http_request='set-header X-Real-IP %[src]'

		uci set haproxy.roundcube_srv=server
		uci set haproxy.roundcube_srv.backend='roundcube'
		uci set haproxy.roundcube_srv.name='roundcube'
		uci set haproxy.roundcube_srv.address='192.168.255.1'
		uci set haproxy.roundcube_srv.port="$port"
		uci set haproxy.roundcube_srv.weight='100'
		uci set haproxy.roundcube_srv.check='1'
		uci set haproxy.roundcube_srv.enabled='1'
	fi

	if ! uci -q get haproxy.${vhost_name} >/dev/null 2>&1; then
		log "Creating HAProxy vhost for $domain..."
		uci set haproxy.${vhost_name}=vhost
		uci set haproxy.${vhost_name}.domain="$domain"
		uci set haproxy.${vhost_name}.backend='roundcube'
		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}.waf_bypass='1'
		uci set haproxy.${vhost_name}.enabled='1'
	fi

	uci commit haproxy
	haproxyctl generate 2>/dev/null
	haproxyctl reload 2>/dev/null

	log "HAProxy configured for $domain"
}

cmd_install() {
	require_root
	log "Installing Roundcube LXC..."

	defaults

	if ! lxc_exists; then
		bootstrap_alpine
	fi

	create_lxc_config
	create_startup_script

	lxc-start -n "$CONTAINER" -d
	sleep 3

	if lxc_running; then
		install_packages
		download_roundcube
		configure_roundcube
		lxc-stop -n "$CONTAINER"
	else
		error "Failed to start container"
		return 1
	fi

	configure_haproxy

	uci_set main.enabled '1'
	uci commit ${CONFIG}

	log "Roundcube installed!"
	log "Start with: roundcubectl start"
}

cmd_start() {
	require_root

	if lxc_running; then
		log "Roundcube already running"
		return 0
	fi

	if ! lxc_exists; then
		error "Roundcube not installed"
		return 1
	fi

	defaults
	create_lxc_config

	log "Starting Roundcube LXC..."
	lxc-start -n "$CONTAINER" -d
	sleep 3

	if lxc_running; then
		log "Roundcube started on port $port"
	else
		error "Failed to start Roundcube"
		return 1
	fi
}

cmd_stop() {
	require_root

	if ! lxc_running; then
		log "Roundcube is not running"
		return 0
	fi

	log "Stopping Roundcube..."
	lxc-stop -n "$CONTAINER"
	log "Roundcube stopped"
}

cmd_restart() {
	cmd_stop
	sleep 2
	cmd_start
}

cmd_status() {
	defaults

	echo ""
	echo "========================================"
	echo "  SecuBox Roundcube v$VERSION (LXC)"
	echo "========================================"
	echo ""

	echo "Configuration:"
	echo "  Port:       $port"
	echo "  Mail Host:  $mail_host"
	echo "  Domain:     $domain"
	echo ""

	echo "Container:"
	if lxc_running; then
		echo -e "  Status:     ${GREEN}Running${NC}"
		local test=$(curl -sI "http://127.0.0.1:$port/" 2>/dev/null | head -1)
		if echo "$test" | grep -q "200"; then
			echo -e "  Web:        ${GREEN}OK${NC}"
		else
			echo -e "  Web:        ${YELLOW}Starting...${NC}"
		fi
	elif lxc_exists; then
		echo -e "  Status:     ${YELLOW}Stopped${NC}"
	else
		echo -e "  Status:     ${RED}Not installed${NC}"
	fi
	echo ""
}

show_help() {
	cat << EOF
SecuBox Roundcube Webmail v$VERSION (LXC)

Usage: roundcubectl <command>

Commands:
  install     Install LXC container
  start       Start Roundcube
  stop        Stop Roundcube
  restart     Restart Roundcube
  status      Show status

EOF
}

case "${1:-}" in
	install)     shift; cmd_install "$@" ;;
	start)       shift; cmd_start "$@" ;;
	stop)        shift; cmd_stop "$@" ;;
	restart)     shift; cmd_restart "$@" ;;
	status)      shift; cmd_status "$@" ;;
	service-run) cmd_start ;;
	service-stop) cmd_stop ;;
	help|--help|-h|'') show_help ;;
	*)           error "Unknown command: $1"; show_help >&2; exit 1 ;;
esac

exit 0
