#!/opt/local/bin/bash
# Cache Cleanup Module
set -euo pipefail
# Preflight TCC prompts once to avoid mid-run interruptions.
check_tcc_permissions() {
    [[ -t 1 ]] || return 0
    local permission_flag="$HOME/.cache/mole/permissions_granted"
    [[ -f "$permission_flag" ]] && return 0
    local -a tcc_dirs=(
        "$HOME/Library/Caches"
        "$HOME/Library/Logs"
        "$HOME/Library/Application Support"
        "$HOME/Library/Containers"
        "$HOME/.cache"
    )
    # Quick permission probe (avoid deep scans).
    local needs_permission_check=false
    if ! ls "$HOME/Library/Caches" > /dev/null 2>&1; then
        needs_permission_check=true
    fi
    if [[ "$needs_permission_check" == "true" ]]; then
        echo ""
        echo -e "${BLUE}First-time setup${NC}"
        echo -e "${GRAY}macOS will request permissions to access Library folders.${NC}"
        echo -e "${GRAY}You may see ${GREEN}${#tcc_dirs[@]} permission dialogs${NC}${GRAY} - please approve them all.${NC}"
        echo ""
        echo -ne "${PURPLE}${ICON_ARROW}${NC} Press ${GREEN}Enter${NC} to continue: "
        read -r
        MOLE_SPINNER_PREFIX="" start_inline_spinner "Requesting permissions..."
        # Touch each directory to trigger prompts without deep scanning.
        for dir in "${tcc_dirs[@]}"; do
            [[ -d "$dir" ]] && command find "$dir" -maxdepth 1 -type d > /dev/null 2>&1
        done
        stop_inline_spinner
        echo ""
    fi
    # Mark as granted to avoid repeat prompts.
    ensure_user_file "$permission_flag"
    return 0
}
# Args: $1=browser_name, $2=cache_path
# Clean Service Worker cache while protecting critical web editors.
clean_service_worker_cache() {
    local browser_name="$1"
    local cache_path="$2"
    [[ ! -d "$cache_path" ]] && return 0
    local cleaned_size=0
    local protected_count=0
    while IFS= read -r cache_dir; do
        [[ ! -d "$cache_dir" ]] && continue
        # Extract a best-effort domain name from cache folder.
        local domain=$(basename "$cache_dir" | grep -oE '[a-zA-Z0-9][-a-zA-Z0-9]*\.[a-zA-Z]{2,}' | head -1 || echo "")
        local size=$(run_with_timeout 5 get_path_size_kb "$cache_dir")
        local is_protected=false
        for protected_domain in "${PROTECTED_SW_DOMAINS[@]}"; do
            if [[ "$domain" == *"$protected_domain"* ]]; then
                is_protected=true
                protected_count=$((protected_count + 1))
                break
            fi
        done
        if [[ "$is_protected" == "false" ]]; then
            if [[ "$DRY_RUN" != "true" ]]; then
                safe_remove "$cache_dir" true || true
            fi
            cleaned_size=$((cleaned_size + size))
        fi
    done < <(run_with_timeout 10 sh -c "find '$cache_path' -type d -depth 2 2> /dev/null || true")
    if [[ $cleaned_size -gt 0 ]]; then
        local spinner_was_running=false
        if [[ -t 1 && -n "${INLINE_SPINNER_PID:-}" ]]; then
            stop_inline_spinner
            spinner_was_running=true
        fi
        local cleaned_mb=$((cleaned_size / 1024))
        if [[ "$DRY_RUN" != "true" ]]; then
            if [[ $protected_count -gt 0 ]]; then
                echo -e "  ${GREEN}${ICON_SUCCESS}${NC} $browser_name Service Worker (${cleaned_mb}MB, ${protected_count} protected)"
            else
                echo -e "  ${GREEN}${ICON_SUCCESS}${NC} $browser_name Service Worker (${cleaned_mb}MB)"
            fi
        else
            echo -e "  ${YELLOW}${ICON_DRY_RUN}${NC} $browser_name Service Worker (would clean ${cleaned_mb}MB, ${protected_count} protected)"
        fi
        note_activity
        if [[ "$spinner_was_running" == "true" ]]; then
            MOLE_SPINNER_PREFIX="  " start_inline_spinner "Scanning browser Service Worker caches..."
        fi
    fi
}
# Next.js/Python project caches with tight scan bounds and timeouts.
clean_project_caches() {
    stop_inline_spinner 2> /dev/null || true
    # Fast pre-check before scanning the whole home dir.
    local has_dev_projects=false
    local -a common_dev_dirs=(
        "$HOME/Code"
        "$HOME/Projects"
        "$HOME/workspace"
        "$HOME/github"
        "$HOME/dev"
        "$HOME/work"
        "$HOME/src"
        "$HOME/repos"
        "$HOME/Development"
        "$HOME/www"
        "$HOME/golang"
        "$HOME/go"
        "$HOME/rust"
        "$HOME/python"
        "$HOME/ruby"
        "$HOME/java"
        "$HOME/dotnet"
        "$HOME/node"
    )
    for dir in "${common_dev_dirs[@]}"; do
        if [[ -d "$dir" ]]; then
            has_dev_projects=true
            break
        fi
    done
    # Fallback: look for project markers near $HOME.
    if [[ "$has_dev_projects" == "false" ]]; then
        local -a project_markers=(
            "node_modules"
            ".git"
            "target"
            "go.mod"
            "Cargo.toml"
            "package.json"
            "pom.xml"
            "build.gradle"
        )
        local spinner_active=false
        if [[ -t 1 ]]; then
            MOLE_SPINNER_PREFIX="  "
            start_inline_spinner "Detecting dev projects..."
            spinner_active=true
        fi
        for marker in "${project_markers[@]}"; do
            if run_with_timeout 3 sh -c "find '$HOME' -maxdepth 2 -name '$marker' -not -path '*/Library/*' -not -path '*/.Trash/*' 2>/dev/null | head -1" | grep -q .; then
                has_dev_projects=true
                break
            fi
        done
        if [[ "$spinner_active" == "true" ]]; then
            stop_inline_spinner 2> /dev/null || true
        fi
        [[ "$has_dev_projects" == "false" ]] && return 0
    fi
    if [[ -t 1 ]]; then
        MOLE_SPINNER_PREFIX="  "
        start_inline_spinner "Searching project caches..."
    fi
    local nextjs_tmp_file
    nextjs_tmp_file=$(create_temp_file)
    local pycache_tmp_file
    pycache_tmp_file=$(create_temp_file)
    local find_timeout=10
    # Parallel scans (Next.js and __pycache__).
    (
        command find "$HOME" -P -mount -type d -name ".next" -maxdepth 3 \
            -not -path "*/Library/*" \
            -not -path "*/.Trash/*" \
            -not -path "*/node_modules/*" \
            -not -path "*/.*" \
            2> /dev/null || true
    ) > "$nextjs_tmp_file" 2>&1 &
    local next_pid=$!
    (
        command find "$HOME" -P -mount -type d -name "__pycache__" -maxdepth 3 \
            -not -path "*/Library/*" \
            -not -path "*/.Trash/*" \
            -not -path "*/node_modules/*" \
            -not -path "*/.*" \
            2> /dev/null || true
    ) > "$pycache_tmp_file" 2>&1 &
    local py_pid=$!
    local elapsed=0
    local check_interval=0.2 # Check every 200ms instead of 1s for smoother experience
    while [[ $(echo "$elapsed < $find_timeout" | awk '{print ($1 < $2)}') -eq 1 ]]; do
        if ! kill -0 $next_pid 2> /dev/null && ! kill -0 $py_pid 2> /dev/null; then
            break
        fi
        sleep $check_interval
        elapsed=$(echo "$elapsed + $check_interval" | awk '{print $1 + $2}')
    done
    # Kill stuck scans after timeout.
    for pid in $next_pid $py_pid; do
        if kill -0 "$pid" 2> /dev/null; then
            kill -TERM "$pid" 2> /dev/null || true
            local grace_period=0
            while [[ $grace_period -lt 20 ]]; do
                if ! kill -0 "$pid" 2> /dev/null; then
                    break
                fi
                sleep 0.1
                ((grace_period++))
            done
            if kill -0 "$pid" 2> /dev/null; then
                kill -KILL "$pid" 2> /dev/null || true
            fi
            wait "$pid" 2> /dev/null || true
        else
            wait "$pid" 2> /dev/null || true
        fi
    done
    if [[ -t 1 ]]; then
        stop_inline_spinner
    fi
    while IFS= read -r next_dir; do
        [[ -d "$next_dir/cache" ]] && safe_clean "$next_dir/cache"/* "Next.js build cache" || true
    done < "$nextjs_tmp_file"
    while IFS= read -r pycache; do
        [[ -d "$pycache" ]] && safe_clean "$pycache"/* "Python bytecode cache" || true
    done < "$pycache_tmp_file"
}
