#!/usr/bin/env bash
set -euo pipefail

# Configuration
CACHE_MAX_AGE=300
MRU_SIZE=5

# Debug logging (set DEBUG=1 to enable via environment variable)
DEBUG="${DEBUG:-0}"

debug() {
    [ "$DEBUG" = "1" ] && echo "[DEBUG] $*" >&2 || true
}

# Parse arguments - flags first, then DEV_DIR
NO_CACHE=false
CLEAR_CACHE=false
EDITOR="${EDITOR:-nvim}"
DEV_DIR=""

debug "Starting dev-launcher with args: $*"

for arg in "$@"; do
    case "$arg" in
    --help | -h)
        cat <<EOF
Usage: $0 [DEV_DIR] [OPTIONS]

Options:
  --no-cache      Bypass cache and rescan repositories
  --clear-cache   Clear cache and MRU files
  --help, -h      Show this help message
EOF
        exit 0
        ;;
    --no-cache)
        NO_CACHE=true
        ;;
    --clear-cache)
        CLEAR_CACHE=true
        ;;
    *)
        [ -z "$DEV_DIR" ] && DEV_DIR="$arg"
        ;;
    esac
done

DEV_DIR="${DEV_DIR:-$HOME/Dev}"
debug "DEV_DIR: $DEV_DIR"
debug "NO_CACHE: $NO_CACHE"
debug "CLEAR_CACHE: $CLEAR_CACHE"

# Setup cache files (unique per dev directory)
DEV_DIR_HASH=$(echo -n "$DEV_DIR" | sha256sum | cut -d' ' -f1 | head -c 16)
CACHE_FILE="$HOME/.cache/dev-launcher-cache-${DEV_DIR_HASH}"
MRU_FILE="$HOME/.cache/dev-launcher-mru-${DEV_DIR_HASH}"
debug "CACHE_FILE: $CACHE_FILE"
debug "MRU_FILE: $MRU_FILE"

# Handle --clear-cache
if [ "$CLEAR_CACHE" = true ]; then
    rm -f "$CACHE_FILE" "$MRU_FILE"
    notify-send "Dev Launcher" "Cache cleared" 2>/dev/null || true
    exit 0
fi

# Find git repositories
find_git_repos() {
    debug "find_git_repos: checking cache..."
    if [ "$NO_CACHE" = false ] && [ -f "$CACHE_FILE" ]; then
        local cache_age=$(($(date +%s) - $(stat -c %Y "$CACHE_FILE" 2>/dev/null || echo 0)))
        debug "Cache age: ${cache_age}s (max: ${CACHE_MAX_AGE}s)"
        if [ $cache_age -lt $CACHE_MAX_AGE ]; then
            debug "Using cached repos"
            cat "$CACHE_FILE"
            return
        fi
        debug "Cache expired, rescanning..."
    fi

    debug "Scanning for git repositories in $DEV_DIR..."
    if command -v fd >/dev/null 2>&1; then
        debug "Using fd for scanning"
        fd -H -t d "^\.git$" "$DEV_DIR" -d 3 -0 | xargs -0 -n1 dirname | sort -u >"$CACHE_FILE"
    else
        debug "Using find for scanning"
        find "$DEV_DIR" -maxdepth 3 -type d -name ".git" -print0 |
            xargs -0 -n1 dirname | sort -u >"$CACHE_FILE"
    fi
    local repo_count=$(wc -l <"$CACHE_FILE")
    debug "Found $repo_count repositories"
    cat "$CACHE_FILE"
}

# Get sanitized project name for tmux session
get_project_name() {
    basename "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g'
}

# Update MRU list
update_mru() {
    local selected="$1"
    local temp_file
    temp_file=$(mktemp)

    echo "$selected" >"$temp_file"
    [ -f "$MRU_FILE" ] && grep -vFx "$selected" "$MRU_FILE" >>"$temp_file" || true
    head -n "$MRU_SIZE" "$temp_file" >"$MRU_FILE"
    rm -f "$temp_file"
}

# Sort by MRU (MRU items first with ⭐, then others)
sort_by_mru() {
    local all_repos="$1"
    local mru_list
    local temp_file

    [ -f "$MRU_FILE" ] && mru_list=$(grep -v '^$' "$MRU_FILE") || mru_list=""

    # If MRU list is empty, just return sorted repos
    if [ -z "$mru_list" ]; then
        echo "$all_repos" | sort
        return
    fi

    # Output MRU items first with indicator
    echo "$mru_list" | sed 's/^/⭐ /'

    # Output non-MRU items using comm (fast set difference)
    temp_file=$(mktemp)
    echo "$all_repos" | sort >"$temp_file.all"
    echo "$mru_list" | sort >"$temp_file.mru"
    comm -23 "$temp_file.all" "$temp_file.mru" 2>/dev/null || cat "$temp_file.all"
    rm -f "$temp_file.all" "$temp_file.mru"
}

# Main execution
REPOS=$(find_git_repos)

if [ -z "$REPOS" ]; then
    debug "No repositories found!"
    notify-send "Dev Launcher" "No git repositories found in $DEV_DIR" 2>/dev/null || true
    exit 1
fi
debug "Found repositories, proceeding..."

# Build display list (relative paths) and mapping
DISPLAY_LIST=$(echo "$REPOS" | sed "s|^${DEV_DIR}/||")
declare -A DISPLAY_TO_PATH

debug "Building display mapping..."
while IFS=$'\t' read -r repo display; do
    DISPLAY_TO_PATH["$display"]="$repo"
done < <(paste <(echo "$REPOS") <(echo "$DISPLAY_LIST"))
debug "Mapped ${#DISPLAY_TO_PATH[@]} projects"

# Sort by MRU and present in tofi
debug "Sorting by MRU..."
SORTED_LIST=$(sort_by_mru "$DISPLAY_LIST")
debug "Presenting in tofi..."
SELECTED_DISPLAY=$(echo "$SORTED_LIST" | tofi \
    --prompt-text "💀 Poison: " \
    --fuzzy-match true \
    --width 30% \
    --height 50% \
    --anchor center \
    --padding-left 20 \
    --padding-right 20 \
    --padding-top 15 \
    --padding-bottom 15 \
    --border-width 2 \
    --outline-width 0 \
    --font "$(fc-match -f '%{family}' 2>/dev/null || echo 'sans')" \
    --font-size 16 \
    --background-color '#191724' \
    --text-color '#e0def4' \
    --selection-color '#31748f' \
    --selection-background '#1f1d2e' \
    --border-color '#31748f' \
    --prompt-color '#f6c177')

debug "Selected display: '$SELECTED_DISPLAY'"
[ -z "$SELECTED_DISPLAY" ] && debug "No selection, exiting" && exit 0

# Remove star indicator and lookup path
SELECTED_DISPLAY_CLEAN=$(echo "$SELECTED_DISPLAY" | sed 's/^⭐ //')
SELECTED="${DISPLAY_TO_PATH[$SELECTED_DISPLAY_CLEAN]:-}"

debug "Selected display (clean): '$SELECTED_DISPLAY_CLEAN'"
debug "Selected path: '$SELECTED'"

[ -z "$SELECTED" ] || [ ! -d "$SELECTED" ] && debug "Invalid selection, exiting" && exit 0

# Update MRU and launch
debug "Updating MRU..."
update_mru "$SELECTED_DISPLAY_CLEAN"

PROJECT_NAME=$(get_project_name "$SELECTED")
SESSION_NAME="dev-${PROJECT_NAME}"
CLASS_NAME="com.mzunino.dev.${PROJECT_NAME}"

debug "Project name: $PROJECT_NAME"
debug "Session name: $SESSION_NAME"
debug "Class name: $CLASS_NAME"
debug "Launching ghostty with launch-or-focus..."

launch-or-focus ghostty \
    --class "$CLASS_NAME" \
    --title "$PROJECT_NAME" \
    --working-directory="$SELECTED" \
    -e bash -c "if tmux has-session -t '$SESSION_NAME' 2>/dev/null; then \
        tmux attach -t '$SESSION_NAME'; \
    else \
        tmux new-session -c '$SELECTED' -s '$SESSION_NAME' -d '$EDITOR'; \
        tmux split-window -h -c '$SELECTED' -t '$SESSION_NAME'; \
        tmux select-pane -t '$SESSION_NAME:0.0'; \
        tmux attach -t '$SESSION_NAME'; \
    fi"
