#!/bin/bash
# Update Manager
# Unified update execution for all update types

set -euo pipefail

# Format Homebrew update label for display
format_brew_update_label() {
    local total="${BREW_OUTDATED_COUNT:-0}"
    if [[ -z "$total" || "$total" -le 0 ]]; then
        return
    fi

    local -a details=()
    local formulas="${BREW_FORMULA_OUTDATED_COUNT:-0}"
    local casks="${BREW_CASK_OUTDATED_COUNT:-0}"

    ((formulas > 0)) && details+=("${formulas} formula")
    ((casks > 0)) && details+=("${casks} cask")

    local detail_str="(${total} updates)"
    if ((${#details[@]} > 0)); then
        detail_str="($(
            IFS=', '
            printf '%s' "${details[*]}"
        ))"
    fi
    printf "  • Homebrew %s" "$detail_str"
}

brew_has_outdated() {
    local kind="${1:-formula}"
    command -v brew > /dev/null 2>&1 || return 1

    if [[ "$kind" == "cask" ]]; then
        brew outdated --cask --quiet 2> /dev/null | grep -q .
    else
        brew outdated --quiet 2> /dev/null | grep -q .
    fi
}

# Ask user if they want to update
# Returns: 0 if yes, 1 if no
ask_for_updates() {
    local has_updates=false
    local -a update_list=()

    local brew_entry
    brew_entry=$(format_brew_update_label || true)
    if [[ -n "$brew_entry" ]]; then
        has_updates=true
        update_list+=("$brew_entry")
    fi

    if [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]]; then
        has_updates=true
        update_list+=("  • App Store (${APPSTORE_UPDATE_COUNT} apps)")
    fi

    if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
        has_updates=true
        update_list+=("  • macOS system")
    fi

    if [[ -n "${MOLE_UPDATE_AVAILABLE:-}" && "${MOLE_UPDATE_AVAILABLE}" == "true" ]]; then
        has_updates=true
        update_list+=("  • Mole")
    fi

    if [[ "$has_updates" == "false" ]]; then
        return 1
    fi

    echo -e "${BLUE}AVAILABLE UPDATES${NC}"
    for item in "${update_list[@]}"; do
        echo -e "$item"
    done
    echo ""
    echo -ne "${YELLOW}Update all now?${NC} ${GRAY}Enter confirm / ESC cancel${NC}: "

    local key
    if ! key=$(read_key); then
        echo "skip"
        echo ""
        return 1
    fi

    if [[ "$key" == "ENTER" ]]; then
        echo "yes"
        echo ""
        return 0
    else
        echo "skip"
        echo ""
        return 1
    fi
}

# Perform all pending updates
# Returns: 0 if all succeeded, 1 if some failed
perform_updates() {
    local updated_count=0
    local total_count=0
    local brew_formula="${BREW_FORMULA_OUTDATED_COUNT:-0}"
    local brew_cask="${BREW_CASK_OUTDATED_COUNT:-0}"

    # Get update labels
    local -a appstore_labels=()
    if [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]]; then
        while IFS= read -r label; do
            [[ -n "$label" ]] && appstore_labels+=("$label")
        done < <(get_appstore_update_labels || true)
    fi

    local -a macos_labels=()
    if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
        while IFS= read -r label; do
            [[ -n "$label" ]] && macos_labels+=("$label")
        done < <(get_macos_update_labels || true)
    fi

    # Check fallback needed
    local appstore_needs_fallback=false
    local macos_needs_fallback=false
    if [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 && ${#appstore_labels[@]} -eq 0 ]]; then
        appstore_needs_fallback=true
    fi
    if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" && ${#macos_labels[@]} -eq 0 ]]; then
        macos_needs_fallback=true
    fi

    # Count total updates
    ((brew_formula > 0)) && ((total_count++))
    ((brew_cask > 0)) && ((total_count++))
    [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]] && ((total_count++))
    [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]] && ((total_count++))
    [[ -n "${MOLE_UPDATE_AVAILABLE:-}" && "${MOLE_UPDATE_AVAILABLE}" == "true" ]] && ((total_count++))

    # Update Homebrew formulae
    if ((brew_formula > 0)); then
        if ! brew_has_outdated "formula"; then
            echo -e "${GRAY}-${NC} Homebrew formulae already up to date"
            ((total_count--))
            echo ""
        else
            echo -e "${BLUE}Updating Homebrew formulae...${NC}"
            local spinner_started=false
            if [[ -t 1 ]]; then
                start_inline_spinner "Running brew upgrade"
                spinner_started=true
            fi

            local brew_output=""
            local brew_status=0
            if ! brew_output=$(brew upgrade --formula 2>&1); then
                brew_status=$?
            fi

            if [[ "$spinner_started" == "true" ]]; then
                stop_inline_spinner
            fi

            local filtered_output
            filtered_output=$(echo "$brew_output" | grep -Ev "^(==>|Warning:)" || true)
            [[ -n "$filtered_output" ]] && echo "$filtered_output"

            if [[ ${brew_status:-0} -eq 0 ]]; then
                echo -e "${GREEN}✓${NC} Homebrew formulae updated"
                reset_brew_cache
                ((updated_count++))
            else
                echo -e "${RED}✗${NC} Homebrew formula update failed"
            fi
            echo ""
        fi
    fi

    # Update Homebrew casks
    if ((brew_cask > 0)); then
        if ! brew_has_outdated "cask"; then
            echo -e "${GRAY}-${NC} Homebrew casks already up to date"
            ((total_count--))
            echo ""
        else
            echo -e "${BLUE}Updating Homebrew casks...${NC}"
            local spinner_started=false
            if [[ -t 1 ]]; then
                start_inline_spinner "Running brew upgrade --cask"
                spinner_started=true
            fi

            local brew_output=""
            local brew_status=0
            if ! brew_output=$(brew upgrade --cask 2>&1); then
                brew_status=$?
            fi

            if [[ "$spinner_started" == "true" ]]; then
                stop_inline_spinner
            fi

            local filtered_output
            filtered_output=$(echo "$brew_output" | grep -Ev "^(==>|Warning:)" || true)
            [[ -n "$filtered_output" ]] && echo "$filtered_output"

            if [[ ${brew_status:-0} -eq 0 ]]; then
                echo -e "${GREEN}✓${NC} Homebrew casks updated"
                reset_brew_cache
                ((updated_count++))
            else
                echo -e "${RED}✗${NC} Homebrew cask update failed"
            fi
            echo ""
        fi
    fi

    # Update App Store apps
    local macos_handled_via_appstore=false
    if [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]]; then
        # Check sudo access
        if ! has_sudo_session; then
            if ! ensure_sudo_session "Software updates require admin access"; then
                echo -e "${YELLOW}☻${NC} App Store updates available — update via System Settings"
                echo ""
                ((total_count--))
                if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
                    ((total_count--))
                fi
            else
                _perform_appstore_update
            fi
        else
            _perform_appstore_update
        fi
    fi

    # Update macOS
    if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" && "$macos_handled_via_appstore" != "true" ]]; then
        if ! has_sudo_session; then
            echo -e "${YELLOW}☻${NC} macOS updates available — update via System Settings"
            echo ""
            ((total_count--))
        else
            _perform_macos_update
        fi
    fi

    # Update Mole
    if [[ -n "${MOLE_UPDATE_AVAILABLE:-}" && "${MOLE_UPDATE_AVAILABLE}" == "true" ]]; then
        echo -e "${BLUE}Updating Mole...${NC}"
        # Try to find mole executable
        local mole_bin="${SCRIPT_DIR}/../../mole"
        [[ ! -f "$mole_bin" ]] && mole_bin=$(command -v mole 2> /dev/null || echo "")

        if [[ -x "$mole_bin" ]]; then
            if "$mole_bin" update 2>&1 | grep -qE "(Updated|latest version)"; then
                echo -e "${GREEN}✓${NC} Mole updated"
                reset_mole_cache
                ((updated_count++))
            else
                echo -e "${RED}✗${NC} Mole update failed"
            fi
        else
            echo -e "${RED}✗${NC} Mole executable not found"
        fi
        echo ""
    fi

    # Summary
    if [[ $total_count -eq 0 ]]; then
        echo -e "${GRAY}No updates to perform${NC}"
        return 0
    elif [[ $updated_count -eq $total_count ]]; then
        echo -e "${GREEN}All updates completed (${updated_count}/${total_count})${NC}"
        return 0
    elif [[ $updated_count -gt 0 ]]; then
        echo -e "${YELLOW}Partial updates completed (${updated_count}/${total_count})${NC}"
        return 0
    else
        echo -e "${RED}No updates were completed${NC}"
        return 0
    fi
}

# Internal: Perform App Store update
_perform_appstore_update() {
    echo -e "${BLUE}Updating App Store apps...${NC}"
    local appstore_log
    appstore_log=$(mktemp "${TMPDIR:-/tmp}/mole-appstore.XXXXXX" 2> /dev/null || echo "/tmp/mole-appstore.log")

    if [[ "$appstore_needs_fallback" == "true" ]]; then
        echo -e "  ${GRAY}Installing all available updates${NC}"
        if sudo softwareupdate -i -a 2>&1 | tee "$appstore_log" | grep -v "^$"; then
            echo -e "${GREEN}✓${NC} Software updates completed"
            ((updated_count++))
            if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
                macos_handled_via_appstore=true
                ((updated_count++))
            fi
        else
            echo -e "${RED}✗${NC} Software update failed"
        fi
    else
        if sudo softwareupdate -i "${appstore_labels[@]}" 2>&1 | tee "$appstore_log" | grep -v "^$"; then
            echo -e "${GREEN}✓${NC} App Store apps updated"
            ((updated_count++))
        else
            echo -e "${RED}✗${NC} App Store update failed"
        fi
    fi
    rm -f "$appstore_log" 2> /dev/null || true
    reset_softwareupdate_cache
    echo ""
}

# Internal: Perform macOS update
_perform_macos_update() {
    echo -e "${BLUE}Updating macOS...${NC}"
    echo -e "${YELLOW}Note:${NC} System update may require restart"

    local macos_log
    macos_log=$(mktemp "${TMPDIR:-/tmp}/mole-macos.XXXXXX" 2> /dev/null || echo "/tmp/mole-macos.log")

    if [[ "$macos_needs_fallback" == "true" ]]; then
        if sudo softwareupdate -i -r 2>&1 | tee "$macos_log" | grep -v "^$"; then
            echo -e "${GREEN}✓${NC} macOS updated"
            ((updated_count++))
        else
            echo -e "${RED}✗${NC} macOS update failed"
        fi
    else
        if sudo softwareupdate -i "${macos_labels[@]}" 2>&1 | tee "$macos_log" | grep -v "^$"; then
            echo -e "${GREEN}✓${NC} macOS updated"
            ((updated_count++))
        else
            echo -e "${RED}✗${NC} macOS update failed"
        fi
    fi

    if grep -qi "restart" "$macos_log" 2> /dev/null; then
        echo -e "${YELLOW}${ICON_WARNING}${NC} Restart required to complete update"
    fi

    rm -f "$macos_log" 2> /dev/null || true
    reset_softwareupdate_cache
    echo ""
}
