#!/usr/bin/env bash
# ffind — cross-shell fuzzy search of text files (filenames + content)
#
# Works in any shell (bash, zsh, fish, sh) and on any Linux distribution:
# the shell execs this binary; the shebang runs it under bash regardless of
# the interactive shell that invoked it.
#
# Depends on: fzf, ripgrep. Optional: wl-clipboard (Wayland), xclip/xsel
# (X11), pbcopy (macOS) for the Ctrl-Y copy binding; xdg-utils for Enter-to-open.
#
# Usage:
#   ffind [dir] [--md]
#   ffind --version
#   ffind -h | --help

set -euo pipefail

VERSION="0.1.0"

usage() {
    cat <<'EOF'
ffind — fuzzy search text files by filename and content

Usage:
  ffind [dir] [--md]
  ffind --version
  ffind -h | --help

Arguments:
  dir       Directory to search (default: current directory)
  --md      Search markdown files only

Options:
  -h, --help      Show this help
  --version       Print version and exit

Keybindings inside fzf:
  Enter         Open the selected file with the default application
  Ctrl-Y        Copy the selected file path to the clipboard
EOF
}

# --- Argument parsing ---
dir="."
md_only=0

for arg in "$@"; do
    case "$arg" in
        --md)
            md_only=1
            ;;
        --version)
            echo "ffind $VERSION"
            exit 0
            ;;
        -h | --help)
            usage
            exit 0
            ;;
        -*)
            printf 'ffind: unknown option: %s\n\n' "$arg" >&2
            usage >&2
            exit 2
            ;;
        *)
            dir="$arg"
            ;;
    esac
done

# --- Dependency checks ---
command -v fzf >/dev/null 2>&1 || {
    printf '\033[1;31mfzf not found\033[0m — install fzf (e.g. "apt install fzf" / "zypper install fzf")\n' >&2
    exit 1
}
command -v rg >/dev/null 2>&1 || {
    printf '\033[1;31mripgrep not found\033[0m — install ripgrep (e.g. "apt install ripgrep" / "zypper install ripgrep")\n' >&2
    exit 1
}

if [ ! -d "$dir" ]; then
    printf '\033[1;31mDirectory not found: %s\033[0m\n' "$dir" >&2
    exit 1
fi

# --- Build the candidate list and run fzf ---
rg_opts=(--files)
if [ "$md_only" -eq 1 ]; then
    rg_opts+=(-g '*.md')
fi

# Filename-only entries + content matches (file:line:text). ffind-preview
# renders either form; --copy extracts the file path from the same line.
selected=$( {
    rg -n "${rg_opts[@]}" "$dir" 2>/dev/null | head -10000
    rg "${rg_opts[@]}" "$dir" 2>/dev/null
} | fzf \
    --prompt=" ffind > " \
    --ansi \
    --height=40 \
    --reverse \
    --border=rounded \
    --margin=0,1 \
    --info=inline \
    --header="Enter: open | Ctrl-Y: copy path" \
    --preview="ffind-preview {}" \
    --preview-window=right:50%:wrap \
    --bind="ctrl-y:execute-silent(ffind-preview --copy {})" \
    --color="bg+:#1a1b26,fg+:#c0caf5,hl+:#ff9e64,info:#7aa2f7,prompt:#7aa2f7,pointer:#ff9e64,marker:#9ece6a,spinner:#9ece6a,header:#565f89" \
    2>/dev/null ) || true

if [ -z "$selected" ]; then
    exit 0
fi

file=$(printf '%s' "$selected" | cut -d: -f1)

printf '\n  Opening: %s\n\n' "$file"
xdg-open "$file" 2>/dev/null || {
    printf '\033[1;31mCould not open: %s\033[0m (xdg-utils installed?)\n' "$file" >&2
    exit 1
}
