#!/bin/bash
# List which compose files can be restored from local backups
# This script checks the compose_registry.json and verifies that all required
# backup files exist in /backup/
#
# Usage:
#   ./list-restorable.sh                          # Show only compose files with all backups available
#   ./list-restorable.sh --all                    # Show all compose files, including those with missing backups
#   ./list-restorable.sh <network>                # Filter by network (e.g., ethereum, arbitrum, polygon)
#   ./list-restorable.sh <network> <chain>        # Filter by network and chain (e.g., ethereum mainnet)
#   ./list-restorable.sh --all <network> <chain>  # Combine with --all flag (--all can be anywhere)
#   ./list-restorable.sh <network> --all <chain>  # --all can be in any position

dir="$(dirname "$0")"
source "$dir/volume-utils.sh"

# Get required persistent volume keys (all volumes minus ephemeral minus optional)
get_required_volume_keys() {
  local compose_file=$1
  local key
  
  while IFS= read -r key; do
    [[ -z "$key" ]] && continue
    # Skip if ephemeral or optional
    if ! is_ephemeral_volume_key "$key" "$compose_file" && ! is_optional_volume_key "$key" "$compose_file"; then
      echo "$key"
    fi
  done < <(get_volume_keys "$compose_file")
}
registry_file="${dir}/compose_registry.json"
backup_dir="/backup"

if [ ! -f "$registry_file" ]; then
    echo "Error: compose_registry.json not found at $registry_file"
    exit 1
fi

if [ ! -d "$backup_dir" ]; then
    echo "Error: /backup directory does not exist"
    exit 1
fi

# Check if jq is available
if ! command -v jq &> /dev/null; then
    echo "Error: jq is required but not installed"
    exit 1
fi

# Parse command-line arguments
# First pass: extract --all/-a flags from anywhere
show_all=false
positional_args=()

for arg in "$@"; do
    case "$arg" in
        --all|-a)
            show_all=true
            ;;
        *)
            positional_args+=("$arg")
            ;;
    esac
done

# Second pass: treat remaining args as positional parameters
# First arg = network, second arg = chain
filter_network=""
filter_chain=""

if [ ${#positional_args[@]} -gt 0 ]; then
    filter_network="${positional_args[0]}"
fi

if [ ${#positional_args[@]} -gt 1 ]; then
    filter_chain="${positional_args[1]}"
fi

# Build jq filter for network and chain
jq_filter=".[]"
if [ -n "$filter_network" ] || [ -n "$filter_chain" ]; then
    condition_parts=()
    if [ -n "$filter_network" ]; then
        condition_parts+=(".network == \"$filter_network\"")
    fi
    if [ -n "$filter_chain" ]; then
        condition_parts+=(".chain == \"$filter_chain\"")
    fi
    # Join conditions with " and "
    if [ ${#condition_parts[@]} -eq 1 ]; then
        condition_str="${condition_parts[0]}"
    elif [ ${#condition_parts[@]} -eq 2 ]; then
        condition_str="${condition_parts[0]} and ${condition_parts[1]}"
    fi
    jq_filter=".[] | select($condition_str)"
fi

# Count filtered entries
if [ -n "$filter_network" ] || [ -n "$filter_chain" ]; then
    total_entries=$(jq -c "$jq_filter" "$registry_file" | wc -l | tr -d ' ')
    filter_info=""
    [ -n "$filter_network" ] && filter_info="${filter_info}network=$filter_network "
    [ -n "$filter_chain" ] && filter_info="${filter_info}chain=$filter_chain "
    echo "Checking $total_entries compose files (filtered by: ${filter_info% }) for restorable backups..."
else
    total_entries=$(jq 'length' "$registry_file")
    echo "Checking $total_entries compose files for restorable backups..."
fi
echo ""

# Use temporary files to collect results (since variables in subshells don't persist)
restorable_list=$(mktemp)
missing_list=$(mktemp)
trap "rm -f $restorable_list $missing_list" EXIT

# Process each entry in the registry
# Use process substitution to avoid subshell issues
while IFS= read -r entry; do
    # Skip empty entries
    if [ -z "$entry" ]; then
        continue
    fi
    
    compose_file=$(echo "$entry" | jq -r '.compose_file')
    
    # Check if compose file exists
    compose_path="${dir}/${compose_file}.yml"
    if [ ! -f "$compose_path" ]; then
        continue
    fi
    
    # Check each required volume for backup file
    all_backups_exist=true
    missing_volumes=()
    backup_info=()
    
    # Required persistent volumes only (exclude ephemeral + optional).
    # Must feed the loop via done<<< / done< <(...) — putting < <(...) on
    # `read` re-runs the producer every iteration and infinite-loops on the
    # first key (vibe regression 2026-08-04 d896378e).
    volumes=$(get_required_volume_keys "$compose_path")
    while IFS= read -r volume; do
        volume_name="rpc_${volume}"
        # jwt/secrets volumes are regenerated at create-node — never backed up by
        # design, so they must not gate restorability (kept plasma marked
        # non-restorable for days despite full data backups being present)
        case "$volume" in *-jwt|*-secrets) continue ;; esac
        # Look for backup files matching pattern: rpc_${volume}-[0-9]*G.tar.zst
        backup_file=$(select_newest_local_backup "$backup_dir" "$volume_name")
        
        if [ -z "$backup_file" ]; then
            all_backups_exist=false
            missing_volumes+=("$volume_name")
        else
            # Extract size and date from filename (format: rpc_<volume>-<date>-<size>G.tar.zst)
            backup_basename=$(basename "$backup_file" .tar.zst)
            # Extract size (the part ending with G before .tar.zst)
            size=$(echo "$backup_basename" | grep -oE '[0-9]+G$' || echo "")
            
            # Try to extract date from filename (format: YYYY-MM-DD-HH-MM-SS)
            # Remove the volume name prefix, then remove the size suffix, what remains should be the date
            if [ -n "$size" ]; then
                # Remove volume prefix and size suffix
                date_candidate=$(echo "$backup_basename" | sed "s/^${volume_name}-//" | sed "s/-${size}$//")
                # Verify it matches the date pattern
                date_str=$(echo "$date_candidate" | grep -oE '^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}$' || echo "")
            else
                date_str=""
            fi
            
            # Calculate age from filename date or file modification time
            if [ -n "$date_str" ]; then
                # Convert date string to timestamp
                # Format: YYYY-MM-DD-HH-MM-SS -> YYYY-MM-DD HH:MM:SS
                date_formatted=$(echo "$date_str" | sed 's/\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)/\1 \2:\3:\4/')
                # Try macOS date format first, then Linux
                backup_timestamp=$(date -j -f "%Y-%m-%d %H:%M:%S" "$date_formatted" +%s 2>/dev/null || \
                                   date -d "$date_formatted" +%s 2>/dev/null || echo "")
            fi
            
            # Fallback to file modification time if date parsing failed
            if [ -z "$backup_timestamp" ] || [ -z "$date_str" ]; then
                # Use file modification time (works on both macOS and Linux)
                if [[ "$OSTYPE" == "darwin"* ]]; then
                    backup_timestamp=$(stat -f %m "$backup_file" 2>/dev/null || echo "")
                else
                    backup_timestamp=$(stat -c %Y "$backup_file" 2>/dev/null || echo "")
                fi
            fi
            
            # Calculate and format age
            if [ -n "$backup_timestamp" ]; then
                current_timestamp=$(date +%s)
                age_seconds=$((current_timestamp - backup_timestamp))
                
                # Format age
                if [ $age_seconds -lt 3600 ]; then
                    age_mins=$((age_seconds / 60))
                    age="${age_mins}m"
                elif [ $age_seconds -lt 86400 ]; then
                    age_hours=$((age_seconds / 3600))
                    age="${age_hours}h"
                elif [ $age_seconds -lt 604800 ]; then
                    age_days=$((age_seconds / 86400))
                    age="${age_days}d"
                else
                    age_weeks=$((age_seconds / 604800))
                    age="${age_weeks}w"
                fi
            else
                age="unknown"
            fi
            
            backup_info+=("${size:-unknown} (${age})")
        fi
    done <<< "$volumes"
    
    if [ "$all_backups_exist" = true ]; then
        # Format backup info for display
        info_str=$(IFS=", "; echo "${backup_info[*]}")
        echo "✓ $compose_file [${info_str}]"
        echo "$compose_file" >> "$restorable_list"
    else
        if [ "$show_all" = true ]; then
            echo "✗ $compose_file (missing: ${missing_volumes[*]})"
            echo "$compose_file" >> "$missing_list"
        fi
    fi
done < <(jq -c "$jq_filter" "$registry_file")

# Count results
restorable_count=$(wc -l < "$restorable_list" 2>/dev/null | tr -d ' ' || echo "0")
missing_count=$(wc -l < "$missing_list" 2>/dev/null | tr -d ' ' || echo "0")

echo ""
echo "Summary:"
echo "  Restorable: $restorable_count"
if [ "$show_all" = true ]; then
    echo "  Missing backups: $missing_count"
fi
echo ""
if [ "$show_all" = false ]; then
    echo "Use --all or -a flag to show compose files with missing backups"
fi
if [ -z "$filter_network" ] && [ -z "$filter_chain" ]; then
    echo "Use --network <name> and/or --chain <name> to filter results"
fi

