#!/bin/bash

# Configuration and directories
CONFIG_FILE="/usrdata/simpleupdates/simpleupdate.conf"

# Define Gitea repository paths
GITEA_HOST="code.060070.xyz"
GITUSER="sky"
REPONAME="simple-admin"
GITTREE="main"

# Monitored directories
DIRECTORIES=("simpleadmin" "socat-at-bridge" "simplefirewall" "tailscale" "ttyd")

# Construct Gitea URL for raw files
BASE_URL="https://$GITEA_HOST/$GITUSER/$REPONAME/raw/branch/$GITTREE"

LOG_FILE="/tmp/simpleupdate.log"

# Load configuration
load_config() {
    if [[ -f "$CONFIG_FILE" ]]; then
        source "$CONFIG_FILE"
    else
        echo "Configuration file ($CONFIG_FILE) not found."
        exit 1
    fi
}

# Function to trim the log file to the last 100 lines
trim_log_file() {
    tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
}

# Function to check for updates
check_for_updates() {
    echo "$(date): Checking for updates..."
    for dir in "${DIRECTORIES[@]}"; do
        local remote_rev=$(wget -qO- "$BASE_URL/$dir/.rev")
        local local_rev_file="/usrdata/$dir/.rev"
        
        if [[ ! -f "$local_rev_file" ]]; then
            echo "No local revision file found for $dir, skipping."
            continue
        fi

        local local_rev=$(cat "$local_rev_file")
        
        if [[ "$remote_rev" -gt "$local_rev" ]]; then
            echo "Update available for $dir, updating..."
            wget -qO "/tmp/update_${dir}.sh" "$BASE_URL/simpleupdates/scripts/update_${dir}.sh"
            chmod +x "/tmp/update_${dir}.sh"
            "/tmp/update_${dir}.sh"
        else
            echo "$dir is up to date."
        fi
    done
    trim_log_file
	wait_to_update
}

# Function to wait and trigger updates based on scheduling
wait_to_update() {
    echo "Waiting for the next update check according to schedule..."
    while true; do
        local current_time=$(date "+%H:%M")
        local current_day=$(date "+%a")
        local current_date=$(date "+%d")

        case $UPDATE_FREQUENCY in
            daily)
                if [[ "$current_time" == "$SCHEDULED_TIME" ]]; then
                    check_for_updates
                fi
                ;;
            weekly)
                if [[ "$current_day" == "$WEEKLY_DAY" && "$current_time" == "$SCHEDULED_TIME" ]]; then
                    check_for_updates
                fi
                ;;
            monthly)
                if [[ "$current_date" == "$MONTHLY_DATE" && "$current_time" == "$SCHEDULED_TIME" ]]; then
                    check_for_updates
                fi
                ;;
            none)
                echo "Update checking is disabled by frequency setting."
                exit 0
                ;;
        esac
        sleep 30  # Sleep for 30 seconds for more granular checks
        trim_log_file
    done
}

# Daemon mode to wait and trigger updates based on scheduling
daemon_mode() {
    load_config
    exec > >(tee -a "$LOG_FILE") 2>&1
    echo "Daemon mode started."
    # Validate only one update frequency is defined
	frequency_count=0
	[[ "$UPDATE_FREQUENCY" == "daily" ]] && ((frequency_count++))
	[[ "$UPDATE_FREQUENCY" == "weekly" ]] && ((frequency_count++))
	[[ "$UPDATE_FREQUENCY" == "monthly" ]] && ((frequency_count++))

	if [[ $frequency_count -gt 1 ]]; then
		echo "Error: More than one update frequency is defined. Exiting."
		exit 1
	elif [[ $frequency_count -eq 0 && "$UPDATE_FREQUENCY" != "none" ]]; then
		echo "Error: No valid update frequency defined. Exiting."
		exit 1
	fi
	if [[ "$CONF_ENABLED" == "no" ]]; then
    echo "Updates are disabled in the configuration."
    exit 0
fi

if [[ "$CHECK_AT_BOOT" == "yes" ]]; then
    check_for_updates
else
    wait_to_update
fi
}

# Function to check for updates
force_check_for_updates() {
    echo "$(date): Checking for updates..."
    for dir in "${DIRECTORIES[@]}"; do
        local remote_rev=$(wget -qO- "$BASE_URL/$dir/.rev")
        local local_rev_file="/usrdata/$dir/.rev"
        
        if [[ ! -f "$local_rev_file" ]]; then
            echo "No local revision file found for $dir, skipping."
            continue
        fi

        local local_rev=$(cat "$local_rev_file")
        
        if [[ "$remote_rev" -gt "$local_rev" ]]; then
            echo "Update available for $dir, updating..."
            wget -qO "/tmp/update_${dir}.sh" "$BASE_URL/simpleupdates/scripts/update_${dir}.sh"
            chmod +x "/tmp/update_${dir}.sh"
            "/tmp/update_${dir}.sh"
        else
            echo "$dir is up to date."
        fi
    done
	exit 0
}

# Helper function to load and update the configuration
update_config() {
    local key="$1"
    local value="$2"
    if grep -q "^$key=" "$CONFIG_FILE"; then
        sed -i "s|^$key=.*|$key=$value|" "$CONFIG_FILE"
    else
        echo "$key=$value" >> "$CONFIG_FILE"
    fi
}

# Display the current configuration status
status() {
    echo "Current Configuration Status:"
    if [[ -f "$CONFIG_FILE" ]]; then
        while IFS= read -r line; do
            echo "$line"
        done < "$CONFIG_FILE"
    else
        echo "Configuration file not found."
    fi
}

# Enable automatic updates
enable_updates() {
    update_config "CONF_ENABLED" "yes"
    echo "Automatic updates have been enabled."
}

# Disable automatic updates
disable_updates() {
    update_config "CONF_ENABLED" "no"
    echo "Automatic updates have been disabled."
}

# Interactive setup for the update configuration
setup() {
    read -p "Enable automatic updates? [yes/no]: " enable_updates
    if [[ "$enable_updates" == "yes" ]]; then
        enable_updates
    else
        disable_updates
    fi

    read -p "Check for updates at boot? [yes/no]: " check_boot
    update_config "CHECK_AT_BOOT" "$check_boot"

    read -p "Update frequency (none, daily, weekly, monthly): " frequency
    update_config "UPDATE_FREQUENCY" "$frequency"

    case $frequency in
        daily)
            read -p "Scheduled time (HH:MM in 24-hour format): " time
            update_config "SCHEDULED_TIME" "$time"
            ;;
        weekly)
            echo "Please enter the day of the week."
            read -p "Day (full name or abbreviation, e.g., Monday or Mon): " day_input
            # Normalize input to abbreviated form
            day_abbr=$(date -d "$day_input" +%a 2>/dev/null)
            if [[ $? -ne 0 ]]; then
                echo "Invalid day of the week. Please try again."
                return 1
            fi
            update_config "WEEKLY_DAY" "$day_abbr"
            read -p "Scheduled time (HH:MM in 24-hour format): " time
            update_config "SCHEDULED_TIME" "$time"
            ;;
        monthly)
            read -p "Date of the month (1-31): " date
            update_config "MONTHLY_DATE" "$date"
            read -p "Scheduled time (HH:MM in 24-hour format): " time
            update_config "SCHEDULED_TIME" "$time"
            ;;
        *)
            echo "No scheduling will be set."
            ;;
    esac

    echo "Update configuration has been set."
}

# Command operations: status, enable, disable, update, setup
case "$1" in
    d)
	daemon_mode
        ;;
    update)
        load_config
        force_check_for_updates
        ;;
    status)
	status
	;;
    enable)
	enable_updates
	;;
    disable)
	disable_updates
	;;
    setup)
	setup
	;;
    *)
        echo "Usage:"
        echo "d: Run as a background check daemon"
        echo "update: Force check for and install updates"
        echo "status: Display current set update schedule"
        echo "enable: Enable automatic updates"
        echo "disable: Disable automatic updates"
        echo "setup: Set up an automatic update schedule"
        ;;
esac
