#!/bin/sh
# SPDX-License-Identifier: Apache-2.0
# LuCI RPC backend for PicoBrew Server
# Copyright (C) 2025 CyberMind.fr

. /lib/functions.sh
. /usr/share/libubox/jshn.sh

CONFIG="picobrew"
LXC_NAME="picobrew"
LXC_PATH="/srv/lxc"
REPO_PATH="/srv/picobrew/app"

# JSON helpers
json_init_obj() { json_init; json_add_object "result"; }
json_close_obj() { json_close_object; json_dump; }

json_error() {
	json_init
	json_add_object "error"
	json_add_string "message" "$1"
	json_close_object
	json_dump
}

json_success() {
	json_init_obj
	json_add_boolean "success" 1
	[ -n "$1" ] && json_add_string "message" "$1"
	json_close_obj
}

# Check if container is running
lxc_running() {
	lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"
}

# Check if container exists
lxc_exists() {
	[ -f "$LXC_PATH/$LXC_NAME/config" ] && [ -d "$LXC_PATH/$LXC_NAME/rootfs" ]
}

# Get service status
get_status() {
	local enabled running installed uptime
	local http_port data_path memory_limit

	config_load "$CONFIG"
	config_get enabled main enabled "0"
	config_get http_port main http_port "8080"
	config_get data_path main data_path "/srv/picobrew"
	config_get memory_limit main memory_limit "512M"

	running="false"
	installed="false"
	uptime=""

	if lxc_exists; then
		installed="true"
	fi

	if lxc_running; then
		running="true"
		uptime=$(lxc-info -n "$LXC_NAME" 2>/dev/null | grep -i "cpu use" | head -1 | awk '{print $3}')
	fi

	# Check if repo exists
	local repo_installed="false"
	[ -d "$REPO_PATH/.git" ] && repo_installed="true"

	# Get LAN IP for URL
	local lan_ip
	lan_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1")

	json_init_obj
	json_add_boolean "enabled" "$( [ "$enabled" = "1" ] && echo 1 || echo 0 )"
	json_add_boolean "running" "$( [ "$running" = "true" ] && echo 1 || echo 0 )"
	json_add_boolean "installed" "$( [ "$installed" = "true" ] && echo 1 || echo 0 )"
	json_add_boolean "repo_installed" "$( [ "$repo_installed" = "true" ] && echo 1 || echo 0 )"
	json_add_string "uptime" "$uptime"
	json_add_int "http_port" "$http_port"
	json_add_string "data_path" "$data_path"
	json_add_string "memory_limit" "$memory_limit"
	json_add_string "web_url" "http://${lan_ip}:${http_port}"
	json_add_string "container_name" "$LXC_NAME"
	json_close_obj
}

# Get configuration
get_config() {
	local http_port http_host data_path memory_limit log_level
	local dns_name https_enabled cert_path key_path
	local default_boil_temp default_mash_temp units

	config_load "$CONFIG"

	# Main settings
	config_get http_port main http_port "8080"
	config_get http_host main http_host "0.0.0.0"
	config_get data_path main data_path "/srv/picobrew"
	config_get memory_limit main memory_limit "512M"
	config_get log_level main log_level "INFO"
	config_get enabled main enabled "0"

	# Server settings
	config_get dns_name server dns_name ""
	config_get https_enabled server https_enabled "0"
	config_get cert_path server cert_path ""
	config_get key_path server key_path ""

	# Brewing settings
	config_get default_boil_temp brewing default_boil_temp "100"
	config_get default_mash_temp brewing default_mash_temp "67"
	config_get units brewing units "metric"

	json_init_obj
	json_add_object "main"
	json_add_boolean "enabled" "$( [ "$enabled" = "1" ] && echo 1 || echo 0 )"
	json_add_int "http_port" "$http_port"
	json_add_string "http_host" "$http_host"
	json_add_string "data_path" "$data_path"
	json_add_string "memory_limit" "$memory_limit"
	json_add_string "log_level" "$log_level"
	json_close_object

	json_add_object "server"
	json_add_string "dns_name" "$dns_name"
	json_add_boolean "https_enabled" "$( [ "$https_enabled" = "1" ] && echo 1 || echo 0 )"
	json_add_string "cert_path" "$cert_path"
	json_add_string "key_path" "$key_path"
	json_close_object

	json_add_object "brewing"
	json_add_int "default_boil_temp" "$default_boil_temp"
	json_add_int "default_mash_temp" "$default_mash_temp"
	json_add_string "units" "$units"
	json_close_object

	json_close_obj
}

# Set configuration value
set_config() {
	local section="$1"
	local option="$2"
	local value="$3"

	if [ -z "$section" ] || [ -z "$option" ]; then
		json_error "Missing section or option"
		return
	fi

	uci set "${CONFIG}.${section}.${option}=${value}"
	uci commit "$CONFIG"

	json_success "Configuration updated"
}

# Start service
start_service() {
	if lxc_running; then
		json_error "Service is already running"
		return
	fi

	if ! lxc_exists; then
		json_error "Container not installed. Run install first."
		return
	fi

	/etc/init.d/picobrew start >/dev/null 2>&1 &

	sleep 2
	if lxc_running; then
		json_success "Service started"
	else
		json_error "Failed to start service"
	fi
}

# Stop service
stop_service() {
	if ! lxc_running; then
		json_error "Service is not running"
		return
	fi

	/etc/init.d/picobrew stop >/dev/null 2>&1

	sleep 2
	if ! lxc_running; then
		json_success "Service stopped"
	else
		json_error "Failed to stop service"
	fi
}

# Restart service
restart_service() {
	/etc/init.d/picobrew restart >/dev/null 2>&1 &

	sleep 3
	if lxc_running; then
		json_success "Service restarted"
	else
		json_error "Service restart failed"
	fi
}

# Install PicoBrew
install() {
	if lxc_exists; then
		json_error "Already installed. Use update to refresh."
		return
	fi

	# Run install in background
	/usr/sbin/picobrewctl install >/var/log/picobrew-install.log 2>&1 &

	json_init_obj
	json_add_boolean "started" 1
	json_add_string "message" "Installation started in background"
	json_add_string "log_file" "/var/log/picobrew-install.log"
	json_close_obj
}

# Uninstall PicoBrew
uninstall() {
	/usr/sbin/picobrewctl uninstall >/dev/null 2>&1

	if ! lxc_exists; then
		json_success "Uninstalled successfully"
	else
		json_error "Uninstall failed"
	fi
}

# Update PicoBrew
update() {
	if ! [ -d "$REPO_PATH/.git" ]; then
		json_error "Not installed. Run install first."
		return
	fi

	# Run update in background
	/usr/sbin/picobrewctl update >/var/log/picobrew-update.log 2>&1 &

	json_init_obj
	json_add_boolean "started" 1
	json_add_string "message" "Update started in background"
	json_add_string "log_file" "/var/log/picobrew-update.log"
	json_close_obj
}

# Get logs
get_logs() {
	local lines="${1:-100}"
	local data_path

	config_load "$CONFIG"
	config_get data_path main data_path "/srv/picobrew"

	json_init_obj
	json_add_array "logs"

	# Get container logs from data path
	if [ -d "$data_path/logs" ]; then
		local logfile
		for logfile in "$data_path/logs"/*.log; do
			[ -f "$logfile" ] || continue
			tail -n "$lines" "$logfile" 2>/dev/null | while IFS= read -r line; do
				json_add_string "" "$line"
			done
		done
	fi

	# Also check install/update logs
	for logfile in /var/log/picobrew-install.log /var/log/picobrew-update.log; do
		[ -f "$logfile" ] || continue
		tail -n 50 "$logfile" 2>/dev/null | while IFS= read -r line; do
			json_add_string "" "$line"
		done
	done

	json_close_array
	json_close_obj
}

# Get brewing sessions (placeholder - depends on picobrew-server API)
get_sessions() {
	local data_path
	config_load "$CONFIG"
	config_get data_path main data_path "/srv/picobrew"

	json_init_obj
	json_add_array "sessions"

	# List session files if they exist
	if [ -d "$data_path/sessions" ]; then
		for session in "$data_path/sessions"/*.json; do
			[ -f "$session" ] || continue
			local name=$(basename "$session" .json)
			json_add_object ""
			json_add_string "id" "$name"
			json_add_string "file" "$session"
			json_close_object
		done
	fi

	json_close_array
	json_close_obj
}

# Get recipes (placeholder - depends on picobrew-server API)
get_recipes() {
	local data_path
	config_load "$CONFIG"
	config_get data_path main data_path "/srv/picobrew"

	json_init_obj
	json_add_array "recipes"

	# List recipe files if they exist
	if [ -d "$data_path/recipes" ]; then
		for recipe in "$data_path/recipes"/*.json; do
			[ -f "$recipe" ] || continue
			local name=$(basename "$recipe" .json)
			json_add_object ""
			json_add_string "id" "$name"
			json_add_string "file" "$recipe"
			json_close_object
		done
	fi

	json_close_array
	json_close_obj
}

# Check install progress
get_install_progress() {
	local log_file="/var/log/picobrew-install.log"
	local status="unknown"
	local progress=0
	local message=""

	if [ -f "$log_file" ]; then
		# Check for completion markers
		if grep -q "Installation complete" "$log_file" 2>/dev/null; then
			status="completed"
			progress=100
			message="Installation completed successfully"
		elif grep -q "ERROR" "$log_file" 2>/dev/null; then
			status="error"
			message=$(grep "ERROR" "$log_file" | tail -1)
		else
			status="running"
			# Estimate progress based on log content
			if grep -q "Extracting rootfs" "$log_file" 2>/dev/null; then
				progress=60
				message="Extracting container rootfs..."
			elif grep -q "Downloading Alpine" "$log_file" 2>/dev/null; then
				progress=40
				message="Downloading Alpine rootfs..."
			elif grep -q "Cloning" "$log_file" 2>/dev/null; then
				progress=20
				message="Cloning PicoBrew repository..."
			else
				progress=10
				message="Starting installation..."
			fi
		fi
	else
		status="not_started"
		message="Installation has not been started"
	fi

	# Check if process is still running
	if pgrep -f "picobrewctl install" >/dev/null 2>&1; then
		status="running"
	fi

	json_init_obj
	json_add_string "status" "$status"
	json_add_int "progress" "$progress"
	json_add_string "message" "$message"
	json_close_obj
}

# Main RPC handler
case "$1" in
	list)
		cat <<-EOF
		{
			"get_status": {},
			"get_config": {},
			"set_config": {"section": "str", "option": "str", "value": "str"},
			"start": {},
			"stop": {},
			"restart": {},
			"install": {},
			"uninstall": {},
			"update": {},
			"get_logs": {"lines": 100},
			"get_sessions": {},
			"get_recipes": {},
			"get_install_progress": {}
		}
		EOF
		;;
	call)
		case "$2" in
			get_status)
				get_status
				;;
			get_config)
				get_config
				;;
			set_config)
				read -r input
				section=$(echo "$input" | jsonfilter -e '@.section' 2>/dev/null)
				option=$(echo "$input" | jsonfilter -e '@.option' 2>/dev/null)
				value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null)
				set_config "$section" "$option" "$value"
				;;
			start)
				start_service
				;;
			stop)
				stop_service
				;;
			restart)
				restart_service
				;;
			install)
				install
				;;
			uninstall)
				uninstall
				;;
			update)
				update
				;;
			get_logs)
				read -r input
				lines=$(echo "$input" | jsonfilter -e '@.lines' 2>/dev/null)
				get_logs "${lines:-100}"
				;;
			get_sessions)
				get_sessions
				;;
			get_recipes)
				get_recipes
				;;
			get_install_progress)
				get_install_progress
				;;
			*)
				json_error "Unknown method: $2"
				;;
		esac
		;;
esac
