#!/bin/bash
set -euo pipefail

# Rapture Kit Installer - validates 9 parts and extracts to Desktop/RAPTURE_KIT*
# Designed for double-click execution (.command) with minimal prompts via osascript dialogs.
# No external dependencies beyond macOS stock tools.

# ---------- Config Defaults ----------
VERSION_DEFAULT="3.1"
BASE_NAME_DEFAULT="Rapture_Kit"
EXTENSIONS=("zio" "zip")   # try .zio first, fallback to .zip
DOWNLOADS_DIR="$HOME/Downloads"
DESKTOP_DIR="$HOME/Desktop"
TARGET_BASENAME="RAPTURE_KIT"
REQUIRED_PARTS=(1 2 3 4 5 6 7 8 9)

# ---------- Helpers ----------
alert() {
	local message="$1"
	/usr/bin/osascript -e "display dialog \"$message\" buttons {\"OK\"} default button 1 with icon caution giving up after 30" >/dev/null 2>&1 || true
	echo "$message"
}

confirm_overwrite() {
	local path="$1"
	/usr/bin/osascript <<EOF 2>/dev/null || true
set theDialogText to "A folder named '$(basename "$path")' already exists on Desktop. What would you like to do?"
display dialog theDialogText buttons {"Cancel", "Keep Both", "Replace"} default button "Keep Both" with icon caution
set theButton to button returned of the result
theButton
EOF
}

# Return a non-existing target path by appending (n)
next_available_path() {
	local base_path="$1"
	if [[ ! -e "$base_path" ]]; then
		echo "$base_path"; return 0
	fi
	local n=2
	while :; do
		local candidate="${base_path}(${n})"
		if [[ ! -e "$candidate" ]]; then
			echo "$candidate"; return 0
		fi
		n=$((n+1))
	done
}

# Compute required space: approximate by total size of zips * 1.1 for overhead
calc_required_bytes() {
	local -a files=("$@")
	local total=0
	local f
	for f in "${files[@]}"; do
		local sz
		sz=$(stat -f%z "$f" 2>/dev/null || echo 0)
		total=$((total + sz))
	done
	# Assume expansion roughly equals compressed total * 3 for safety if unknown
	# User said ~27GB aggregated, so cap at max(current*3, 27GB)
	local thr=$((27 * 1024 * 1024 * 1024))
	local est=$((total * 3))
	if (( est < thr )); then
		est=$thr
	fi
	echo "$est"
}

free_bytes_at_path() {
	local path="$1"
	# Use df -k for bytes calc
	local mount
	mount=$(df -P "$path" | tail -1 | awk '{print $6}')
	local avail_k
	avail_k=$(df -kP "$mount" | tail -1 | awk '{print $4}')
	echo $((avail_k * 1024))
}

human_size() {
	local bytes="$1"
	/usr/bin/awk -v b="$bytes" 'function human(x){s="BKMGTP"; while (x>=1024 && length(s)>1){x/=1024; s=substr(s,2);} return sprintf("%.1f %cB", x, substr(s,1,1));} BEGIN{print human(b)}'
}

# Find files for a given version and extension
find_archives() {
	local version="$1"
	local ext="$2"
	local base="$BASE_NAME_DEFAULT"
	local found=()
	local part
	for part in "${REQUIRED_PARTS[@]}"; do
		local pattern="$DOWNLOADS_DIR/${base}_${version}-Part_${part}_of_9.${ext}"
		if [[ -f "$pattern" ]]; then
			found+=("$pattern")
		fi
	done
	printf '%s\n' "${found[@]}"
}

# Extract archive into target path
extract_zip() {
	local archive_path="$1"
	local dest="$2"
	/usr/bin/unzip -q -o "$archive_path" -d "$dest"
}

# ---------- Main ----------
main() {
	# Gate: ask user to confirm running from Downloads
	if [[ ! -d "$DOWNLOADS_DIR" ]]; then
		alert "Cannot locate your Downloads folder (expected at $DOWNLOADS_DIR). Aborting."; exit 1
	fi

	# Try both extensions and possible versions (exact first, then prompt)
	local version="$VERSION_DEFAULT"
	local found_files=()
	local ext
	for ext in "${EXTENSIONS[@]}"; do
		local files=()
		while IFS= read -r line; do
			files+=("$line")
		done < <(find_archives "$version" "$ext")
		if (( ${#files[@]} == ${#REQUIRED_PARTS[@]} )); then
			found_files=("${files[@]}")
			break
		fi
	done

	if (( ${#found_files[@]} != ${#REQUIRED_PARTS[@]} )); then
		# Prompt for version via dialog
		version=$(/usr/bin/osascript -e 'display dialog "Enter the Rapture Kit version (e.g., 3.1):" default answer "3.1" buttons {"OK"} default button 1' -e 'text returned of the result' 2>/dev/null || echo "$VERSION_DEFAULT")
		for ext in "${EXTENSIONS[@]}"; do
			local files=()
			while IFS= read -r line; do
				files+=("$line")
			done < <(find_archives "$version" "$ext")
			if (( ${#files[@]} == ${#REQUIRED_PARTS[@]} )); then
				found_files=("${files[@]}")
				break
			fi
		done
	fi

	if (( ${#found_files[@]} != ${#REQUIRED_PARTS[@]} )); then
		alert "Could not find all 9 archives in Downloads. Ensure files named like ${BASE_NAME_DEFAULT}_${version}-Part_#_of_9.(zio|zip) are present."; exit 2
	fi

	# Determine target path on Desktop, handle collisions
	local target="$DESKTOP_DIR/$TARGET_BASENAME"
	if [[ -e "$target" ]]; then
		choice="$(confirm_overwrite "$target")"
		case "${choice:-Cancel}" in
			Replace)
				rm -rf "$target" ;;
			"Keep Both")
				target="$(next_available_path "$target")" ;;
			*)
				alert "Installation cancelled."; exit 0 ;;
		esac
	fi
	mkdir -p "$target"

	# Free space check
	local required
	required="$(calc_required_bytes "${found_files[@]}")"
	local free
	free="$(free_bytes_at_path "$target")"
	if (( free < required )); then
		alert "Insufficient disk space. Required: $(human_size "$required"), Free: $(human_size "$free"). Free up space and try again."
		exit 3
	fi

	# Confirm security prompt guidance
	/usr/bin/osascript -e 'display dialog "macOS may prompt for permission. Click OK to continue with installation." buttons {"OK"} default button 1 with icon note' >/dev/null 2>&1 || true

	# Extract in order (already numeric by part)
	local a
	for a in "${found_files[@]}"; do
		echo "Extracting $(basename "$a") ..."
		extract_zip "$a" "$target"
	done

	# Done
	/usr/bin/osascript -e "display dialog \"Rapture Kit installed to: $target\" buttons {\"OK\"} default button 1 with icon note giving up after 30" >/dev/null 2>&1 || true
	echo "Installed to: $target"
}

main "$@"
