#!/bin/bash
# nas-docker-up — Apply Docker updates via docker compose up -d
# Usage: nas-docker-up [stack_name]
#   No argument: updates all containers with a newer image available
#   With argument: updates only the specified stack
# Non-interactive mode (HA): applies directly, no prompt
# Terminal mode: confirmation per stack (unless a specific stack is given)

set -euo pipefail

if [ -t 1 ]; then INTERACTIVE=true; else INTERACTIVE=false; fi

TARGET_STACK="${1:-}"

# Colors (terminal mode only)
if $INTERACTIVE; then
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[1;33m'
    CYAN='\033[0;36m'
    BOLD='\033[1m'
    RESET='\033[0m'
else
    RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
fi

# --- Detect global OMV env file ---
OMV_GLOBAL_ENV=""
if [ -f "/etc/omv-compose.env" ]; then
    OMV_GLOBAL_ENV="/etc/omv-compose.env"
elif [ -f "/srv/omv-compose.env" ]; then
    OMV_GLOBAL_ENV="/srv/omv-compose.env"
fi

# --- Collect containers to update ---
containers_to_update=()
images_to_update=()
compose_dirs=()
container_ids=()
old_versions=()
new_versions=()

if $INTERACTIVE; then
    echo -e "${BOLD}--- Phase 1: Detecting updates ---${RESET}"
fi

while IFS=: read -r container_id container_name; do
    # Filter by stack if argument provided
    if [ -n "$TARGET_STACK" ] && [ "$container_name" != "$TARGET_STACK" ]; then
        stack_label=$(docker inspect --format='{{index .Config.Labels "com.docker.compose.project"}}' "$container_id" 2>/dev/null | xargs)
        if [ "$stack_label" != "$TARGET_STACK" ]; then
            continue
        fi
    fi

    compose_dir=$(docker inspect --format='{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$container_id" 2>/dev/null | xargs)

    if [ -z "$compose_dir" ] || [ ! -d "$compose_dir" ]; then
        continue
    fi

    image_name=$(docker inspect --format='{{.Config.Image}}' "$container_id")
    old_image_id=$(docker inspect --format='{{.Image}}' "$container_id")
    old_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$container_id" 2>/dev/null || echo "")
    [ -z "$old_ver" ] && old_ver="unknown"

    if $INTERACTIVE; then
        echo -ne "  Checking ${CYAN}${container_name}${RESET}... "
    fi

    if ! docker pull "$image_name" > /dev/null 2>&1; then
        if $INTERACTIVE; then echo -e "${YELLOW}⚠ Pull error (skipped)${RESET}"; fi
        continue
    fi

    new_image_id=$(docker inspect --format='{{.Id}}' "$image_name" 2>/dev/null)

    if [ "$old_image_id" != "$new_image_id" ]; then
        new_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$image_name" 2>/dev/null || echo "")
        [ -z "$new_ver" ] && new_ver="available"

        if $INTERACTIVE; then
            echo -e "${YELLOW}UPDATE AVAILABLE${RESET}: ${YELLOW}${old_ver}${RESET} → ${GREEN}${new_ver}${RESET}"
        fi

        containers_to_update+=("$container_name")
        images_to_update+=("$image_name")
        compose_dirs+=("$compose_dir")
        container_ids+=("$container_id")
        old_versions+=("$old_ver")
        new_versions+=("$new_ver")
    else
        if $INTERACTIVE; then echo -e "${GREEN}✅ Up to date${RESET}"; fi
    fi

done < <(docker ps --format "{{.ID}}:{{.Names}}")

if [ ${#containers_to_update[@]} -eq 0 ]; then
    if $INTERACTIVE; then
        echo ""
        echo -e "${GREEN}✅ No containers to update.${RESET}"
    fi
    exit 0
fi

if $INTERACTIVE; then
    echo ""
    echo -e "${BOLD}--- Phase 2: Available updates ---${RESET}"
    for i in "${!containers_to_update[@]}"; do
        echo -e "  • ${CYAN}${containers_to_update[$i]}${RESET}: ${YELLOW}${old_versions[$i]}${RESET} → ${GREEN}${new_versions[$i]}${RESET}"
    done
    echo ""

    # If a specific stack was given, apply directly without asking
    if [ -z "$TARGET_STACK" ]; then
        UPDATE_ALL=false
        while true; do
            read -p "Update ALL containers? [y]es (All) / [n]o (Choose per container): " global_choice
            case "$global_choice" in
                [yY]*) UPDATE_ALL=true; break ;;
                [nN]*) UPDATE_ALL=false; break ;;
                *) echo "Please answer y or n." ;;
            esac
        done
    else
        UPDATE_ALL=true
    fi
fi

# --- Phase 3: Apply ---
if $INTERACTIVE; then
    echo ""
    echo -e "${BOLD}--- Phase 3: Applying updates ---${RESET}"
fi

START_DIR=$(pwd)
upgraded=0
failed=0

for i in "${!containers_to_update[@]}"; do
    c_name="${containers_to_update[$i]}"
    c_dir="${compose_dirs[$i]}"
    c_old_ver="${old_versions[$i]}"
    c_new_ver="${new_versions[$i]}"

    DO_UPDATE=false

    if ! $INTERACTIVE; then
        # HA mode: always apply
        DO_UPDATE=true
    elif [ "$UPDATE_ALL" = true ]; then
        DO_UPDATE=true
    else
        while true; do
            read -p "  Update '${c_name}' (${c_old_ver} → ${c_new_ver})? [y/n]: " choice
            case "$choice" in
                [yY]*) DO_UPDATE=true; break ;;
                [nN]*) DO_UPDATE=false; break ;;
                *) echo "Please answer y or n." ;;
            esac
        done
    fi

    if [ "$DO_UPDATE" = true ]; then
        if $INTERACTIVE; then
            echo -e "  🚀 Updating ${CYAN}${c_name}${RESET} in ${c_dir}..."
        fi

        if cd "$c_dir" 2>/dev/null; then
            ENV_ARGS=""

            # Global OMV env
            if [ -n "$OMV_GLOBAL_ENV" ] && [ -f "$OMV_GLOBAL_ENV" ]; then
                ENV_ARGS="--env-file $OMV_GLOBAL_ENV"
            else
                # Fallback: look for global.env or .env in parent directory
                PARENT_DIR=$(dirname "$c_dir")
                if [ -f "$PARENT_DIR/global.env" ]; then
                    ENV_ARGS="--env-file $PARENT_DIR/global.env"
                elif [ -f "$PARENT_DIR/.env" ]; then
                    ENV_ARGS="--env-file $PARENT_DIR/.env"
                fi
            fi

            # Local .env (always added if present)
            if [ -f ".env" ]; then
                ENV_ARGS="$ENV_ARGS --env-file .env"
            fi

            if docker compose $ENV_ARGS up -d --remove-orphans 2>&1; then
                if $INTERACTIVE; then
                    echo -e "  ${GREEN}✅ ${c_name} updated successfully.${RESET}"
                fi
                upgraded=$((upgraded + 1))
            else
                if $INTERACTIVE; then
                    echo -e "  ${RED}❌ Update failed for ${c_name}.${RESET}"
                fi
                failed=$((failed + 1))
            fi
        else
            if $INTERACTIVE; then
                echo -e "  ${RED}❌ Cannot access ${c_dir}.${RESET}"
            fi
            failed=$((failed + 1))
        fi
    else
        if $INTERACTIVE; then
            echo -e "  ⏭  Skipped: ${c_name}"
        fi
    fi

    cd "$START_DIR"
done

if $INTERACTIVE; then
    echo ""
    echo -e "${BOLD}--- Done ---${RESET}"
    echo -e "  ${GREEN}✅ ${upgraded} updated${RESET}  ${RED}❌ ${failed} failed${RESET}"
else
    printf '{"upgraded":%d,"failed":%d}\n' "$upgraded" "$failed"
fi
