#!/bin/sh
# SecuBox Jellyfin Media Server manager
# LXC-based deployment with HAProxy, Firewall, Mesh P2P integration

VERSION="3.0.0"
CONFIG="jellyfin"
CONTAINER="jellyfin"
LXC_PATH="/srv/lxc/jellyfin"

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

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

# ============================================================================
# Configuration Helpers
# ============================================================================

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() {
	data_path="$(uci_get main.data_path)"
	[ -z "$data_path" ] && data_path="/srv/jellyfin"
	media_path="$(uci_get main.media_path)"
	[ -z "$media_path" ] && media_path="/srv/SHARE"
	port="$(uci_get main.port)"
	[ -z "$port" ] && port="8096"
	ip_address="$(uci_get main.ip_address)"
	[ -z "$ip_address" ] && ip_address="192.168.255.31"
	domain="$(uci_get network.domain)"
	[ -z "$domain" ] && domain="jellyfin.secubox.local"
}

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 = jellyfin
lxc.rootfs.path = dir:${LXC_PATH}/rootfs
lxc.net.0.type = veth
lxc.net.0.link = br-lan
lxc.net.0.flags = up
lxc.net.0.ipv4.address = ${ip_address}/24
lxc.net.0.ipv4.gateway = 192.168.255.1
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.mount.entry = ${media_path} srv/SHARE none bind,ro 0 0
lxc.mount.entry = ${data_path}/config config none bind 0 0
lxc.mount.entry = ${data_path}/cache cache none bind 0 0
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 = 2048000000
lxc.init.cmd = /opt/start-jellyfin.sh
EOF
}

create_startup_script() {
	cat > "$LXC_PATH/rootfs/opt/start-jellyfin.sh" << 'EOF'
#!/bin/bash
export PATH=/usr/lib/jellyfin-ffmpeg:$PATH
export LD_LIBRARY_PATH=/usr/lib/jellyfin-ffmpeg/lib:$LD_LIBRARY_PATH

echo "Starting Jellyfin..."
exec /jellyfin/jellyfin \
    --datadir=/config \
    --cachedir=/cache \
    --webdir=/jellyfin/jellyfin-web
EOF
	chmod +x "$LXC_PATH/rootfs/opt/start-jellyfin.sh"
}

# ============================================================================
# HAProxy Integration
# ============================================================================

configure_haproxy() {
	local haproxy_enabled=$(uci_get network.haproxy)
	[ "$haproxy_enabled" != "1" ] && { log "HAProxy integration disabled in UCI"; return 0; }

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

	defaults

	# Check if backend already exists
	if uci -q get haproxy.jellyfin_web >/dev/null 2>&1; then
		log "HAProxy backend jellyfin_web already exists, updating..."
		uci set haproxy.jellyfin_web.server="media ${ip_address}:${port} weight 100 check"
	else
		log "Creating HAProxy backend..."
		uci set haproxy.jellyfin_web=backend
		uci set haproxy.jellyfin_web.name='jellyfin_web'
		uci set haproxy.jellyfin_web.mode='http'
		uci set haproxy.jellyfin_web.balance='roundrobin'
		uci set haproxy.jellyfin_web.enabled='1'
		uci set haproxy.jellyfin_web.server="media ${ip_address}:${port} weight 100 check"
	fi

	# Check if vhost already exists
	local vhost_name=$(echo "$domain" | tr '.' '_')
	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='jellyfin_web'
		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 -> ${ip_address}:${port}"
}

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

cmd_install() {
	require_root
	log "Installing Jellyfin LXC container..."

	defaults
	ensure_dir "$LXC_PATH"
	ensure_dir "$LXC_PATH/rootfs/srv/SHARE"
	ensure_dir "$LXC_PATH/rootfs/config"
	ensure_dir "$LXC_PATH/rootfs/cache"
	ensure_dir "$LXC_PATH/rootfs/opt"
	ensure_dir "$data_path/config"
	ensure_dir "$data_path/cache"

	if [ ! -f "$LXC_PATH/rootfs/jellyfin/jellyfin" ]; then
		log "Jellyfin rootfs not found. Please extract from Docker image:"
		echo "  docker pull jellyfin/jellyfin:latest"
		echo "  docker create --name temp-jellyfin jellyfin/jellyfin:latest"
		echo "  docker export temp-jellyfin > /tmp/jellyfin.tar"
		echo "  tar -xf /tmp/jellyfin.tar -C $LXC_PATH/rootfs/"
		echo "  docker rm temp-jellyfin"
		return 1
	fi

	create_lxc_config
	create_startup_script

	# Symlink ffmpeg if needed
	if [ -d "$LXC_PATH/rootfs/usr/lib/jellyfin-ffmpeg" ]; then
		ln -sf /usr/lib/jellyfin-ffmpeg/ffmpeg "$LXC_PATH/rootfs/usr/bin/ffmpeg" 2>/dev/null
		ln -sf /usr/lib/jellyfin-ffmpeg/ffprobe "$LXC_PATH/rootfs/usr/bin/ffprobe" 2>/dev/null
	fi

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

	configure_haproxy

	log "Jellyfin LXC installed successfully!"
	log "Start with: jellyfinctl start"
}

# ============================================================================
# Service Control
# ============================================================================

cmd_start() {
	require_root

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

	if ! lxc_exists; then
		error "Jellyfin not installed. Run 'jellyfinctl install' first"
		return 1
	fi

	defaults
	create_lxc_config

	log "Starting Jellyfin LXC..."
	lxc-start -n "$CONTAINER" -d
	sleep 5

	if lxc_running; then
		log "Jellyfin started at http://${ip_address}:${port}"
	else
		error "Failed to start Jellyfin"
		return 1
	fi
}

cmd_stop() {
	require_root

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

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

cmd_restart() {
	cmd_stop
	sleep 2
	cmd_start
}

# ============================================================================
# Status
# ============================================================================

cmd_status() {
	defaults

	echo ""
	echo "========================================"
	echo "  Jellyfin Media Server v$VERSION (LXC)"
	echo "========================================"
	echo ""

	local enabled=$(uci_get main.enabled)
	echo "Configuration:"
	echo "  Enabled:    $([ "$enabled" = "1" ] && echo -e "${GREEN}Yes${NC}" || echo -e "${RED}No${NC}")"
	echo "  IP Address: $ip_address"
	echo "  Port:       $port"
	echo "  Data:       $data_path"
	echo "  Media:      $media_path"
	echo "  Domain:     $domain"
	echo ""

	echo "Container:"
	if lxc_running; then
		echo -e "  Status:     ${GREEN}Running${NC}"
		local pid=$(lxc-info -n "$CONTAINER" 2>/dev/null | grep PID | awk '{print $2}')
		echo "  PID:        $pid"

		# Health check
		local health=$(curl -s "http://${ip_address}:${port}/health" 2>/dev/null)
		if [ "$health" = "Healthy" ]; then
			echo -e "  Health:     ${GREEN}Healthy${NC}"
		else
			echo -e "  Health:     ${YELLOW}Starting...${NC}"
		fi
	elif lxc_exists; then
		echo -e "  Status:     ${YELLOW}Stopped${NC}"
	else
		echo -e "  Status:     ${RED}Not installed${NC}"
	fi
	echo ""

	# Storage
	if [ -d "$data_path" ]; then
		local disk=$(du -sh "$data_path" 2>/dev/null | cut -f1)
		echo "Storage:"
		echo "  Data size:  ${disk:-unknown}"
	fi

	echo ""
}

# ============================================================================
# Logs & Shell
# ============================================================================

cmd_logs() {
	defaults
	if [ -f "$data_path/config/log/log_$(date +%Y%m%d).log" ]; then
		tail "${@:--100}" "$data_path/config/log/log_$(date +%Y%m%d).log"
	else
		ls -la "$data_path/config/log/" 2>/dev/null || echo "No logs found"
	fi
}

cmd_shell() {
	if ! lxc_running; then
		error "Container not running"
		return 1
	fi
	lxc-attach -n "$CONTAINER" -- /bin/bash 2>/dev/null || lxc-attach -n "$CONTAINER" -- /bin/sh
}

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

show_help() {
	cat << EOF
Jellyfin Media Server Control v$VERSION (LXC)

Usage: jellyfinctl <command> [options]

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

  logs [-f] [--tail N] Show logs
  shell                Open shell inside container

  configure-haproxy    Configure HAProxy vhost

Examples:
  jellyfinctl install
  jellyfinctl start
  jellyfinctl status
  jellyfinctl logs -100

EOF
}

case "${1:-}" in
	install)            shift; cmd_install "$@" ;;
	start)              shift; cmd_start "$@" ;;
	stop)               shift; cmd_stop "$@" ;;
	restart)            shift; cmd_restart "$@" ;;
	status)             shift; cmd_status "$@" ;;
	logs)               shift; cmd_logs "$@" ;;
	shell)              shift; cmd_shell "$@" ;;
	configure-haproxy)  configure_haproxy ;;
	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
