#!/usr/bin/env bash

set -o pipefail

# ============================================================
# Hastebin / pste.us uploader
#
# Dependencies:
#   curl jq gum fzf qrencode
#
# Optional:
#   wl-copy / xclip / xsel / pbcopy
#   xdg-open / open
#
# Examples:
#   ./haste
#   ./haste file.txt
#   ./haste file.txt --open
#   ./haste file.txt --no-qr
#   ./haste file.txt --quiet
#   ./haste --history
# ============================================================

# -----------------------------
# Configuration
# -----------------------------

UPLOAD_URL="https://pste.us/documents"
BASE_URL="https://pste.us"

HISTORY_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/haste"
HISTORY_FILE="$HISTORY_DIR/history"

# Colors
PINK="#f5c2e7"
BLUE="#89b4fa"
GREEN="#a6e3a1"
RED="#f38ba8"
YELLOW="#f9e2af"
CYAN="#89dceb"
TEXT="#cdd6f4"
MAUVE="#cba6f7"

# Temporary files
RESPONSE_FILE=""
PROGRESS_FILE=""

# -----------------------------
# Cleanup
# -----------------------------

cleanup() {
    [[ -n "$RESPONSE_FILE" && -f "$RESPONSE_FILE" ]] && rm -f "$RESPONSE_FILE"
    [[ -n "$PROGRESS_FILE" && -f "$PROGRESS_FILE" ]] && rm -f "$PROGRESS_FILE"
}

trap cleanup EXIT
trap 'exit 130' INT TERM

# -----------------------------
# Helpers
# -----------------------------

die() {
    gum style \
        --foreground "$RED" \
        --border double \
        --border-foreground "$RED" \
        --padding "1 2" \
        "✗ $1"

    exit 1
}

info() {
    gum style \
        --foreground "$CYAN" \
        --padding "0 1" \
        "$1"
}

success() {
    gum style \
        --foreground "$GREEN" \
        --padding "0 1" \
        "✓ $1"
}

warning() {
    gum style \
        --foreground "$YELLOW" \
        --padding "0 1" \
        "⚠ $1"
}

# -----------------------------
# Dependency check
# -----------------------------

REQUIRED_COMMANDS=(
    curl
    jq
    gum
    fzf
)

for cmd in "${REQUIRED_COMMANDS[@]}"; do
    if ! command -v "$cmd" &>/dev/null; then
        die "Required command not found: $cmd"
    fi
done

# -----------------------------
# Arguments
# -----------------------------

SHOW_HISTORY=false
OPEN_AFTER=false
SHOW_QR=true
QUIET=false
FILE_PATH=""

while [[ $# -gt 0 ]]; do
    case "$1" in
        --history|-H)
            SHOW_HISTORY=true
            shift
            ;;

        --open|-o)
            OPEN_AFTER=true
            shift
            ;;

        --no-qr)
            SHOW_QR=false
            shift
            ;;

        --quiet|-q)
            QUIET=true
            shift
            ;;

        --help|-h)
            cat <<EOF
Usage:
  haste [FILE]
  haste [OPTIONS] [FILE]

Options:
  -H, --history    Show upload history
  -o, --open       Open URL in browser
  -q, --quiet      Print only the URL
      --no-qr      Don't display QR code
  -h, --help       Show this help

Examples:
  haste
  haste file.txt
  haste file.txt --open
  haste file.txt --no-qr
  haste file.txt --quiet
  haste --history
EOF
            exit 0
            ;;

        -*)
            die "Unknown option: $1"
            ;;

        *)
            FILE_PATH="$1"
            shift
            ;;
    esac
done

# -----------------------------
# History
# -----------------------------

show_history() {
    if [[ ! -f "$HISTORY_FILE" || ! -s "$HISTORY_FILE" ]]; then
        warning "No upload history yet."
        exit 0
    fi

    echo

    gum style \
        --foreground "$MAUVE" \
        --border double \
        --border-foreground "$MAUVE" \
        --align center \
        --width 70 \
        --padding "0 2" \
        "UPLOAD HISTORY"

    echo

    # Format:
    # timestamp|filename|url
    HISTORY_SELECTION=$(
        tac "$HISTORY_FILE" |
        awk -F'|' '{
            printf "%s  │  %s  │  %s\n", $2, $3, $1
        }' |
        gum choose \
            --height 15 \
            --cursor "➜ " \
            --header "Select an upload"
    )

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

    SELECTED_URL=$(printf '%s\n' "$HISTORY_SELECTION" | awk -F'  │  ' '{print $2}')

    echo
    echo -e "\033[36m$SELECTED_URL\033[0m"
    echo

    if gum confirm "Copy this URL to clipboard?"; then
        if command -v wl-copy &>/dev/null; then
            printf '%s' "$SELECTED_URL" | wl-copy
            success "Copied to clipboard."
        elif command -v xclip &>/dev/null; then
            printf '%s' "$SELECTED_URL" | xclip -selection clipboard
            success "Copied to clipboard."
        elif command -v xsel &>/dev/null; then
            printf '%s' "$SELECTED_URL" | xsel --clipboard --input
            success "Copied to clipboard."
        elif command -v pbcopy &>/dev/null; then
            printf '%s' "$SELECTED_URL" | pbcopy
            success "Copied to clipboard."
        else
            warning "No clipboard utility found."
        fi
    fi

    if gum confirm "Open this URL in browser?"; then
        if command -v xdg-open &>/dev/null; then
            xdg-open "$SELECTED_URL" &>/dev/null &
        elif command -v open &>/dev/null; then
            open "$SELECTED_URL" &>/dev/null &
        else
            warning "No browser opener found."
        fi
    fi

    exit 0
}

if [[ "$SHOW_HISTORY" == true ]]; then
    show_history
fi

# -----------------------------
# File selection
# -----------------------------

if [[ -z "$FILE_PATH" ]]; then

    FILE_PATH=$(
        find . -maxdepth 1 -type f -printf '%f\n' |
        fzf \
            --prompt="   Select file to upload: " \
            --border \
            --reverse \
            --header="Use ↑/↓ to select, <Enter> to confirm" \
            --pointer="➤" \
            --color="bg+:#1e1e2e,bg:#181825,spinner:#f5c2e7,hl:#f38ba8,fg:#cdd6f4,header:#89b4fa,info:#f9e2af,pointer:#a6e3a1,marker:#f5c2e7,fg+:#cdd6f4,prompt:#89b4fa,hl+:#f38a8a" \
            --preview='bat --style=numbers --color=always {}'
    )

    if [[ -z "$FILE_PATH" ]]; then
        warning "No file selected."
        exit 1
    fi
fi

# -----------------------------
# Validate file
# -----------------------------

if [[ ! -f "$FILE_PATH" ]]; then
    die "File does not exist: $FILE_PATH"
fi

if [[ ! -r "$FILE_PATH" ]]; then
    die "File is not readable: $FILE_PATH"
fi

# -----------------------------
# File information
# -----------------------------

FILE_NAME="$(basename "$FILE_PATH")"

if command -v numfmt &>/dev/null; then
    FILE_BYTES=$(stat -c%s "$FILE_PATH" 2>/dev/null || stat -f%z "$FILE_PATH")
    FILE_SIZE=$(numfmt --to=iec --suffix=B "$FILE_BYTES" 2>/dev/null || echo "${FILE_BYTES} B")
else
    FILE_SIZE=$(du -h "$FILE_PATH" | cut -f1)
fi

FILE_TYPE=$(file -b "$FILE_PATH" 2>/dev/null || echo "Unknown")

if [[ -r "$FILE_PATH" ]]; then
    LINE_COUNT=$(wc -l < "$FILE_PATH" 2>/dev/null || echo "N/A")
else
    LINE_COUNT="N/A"
fi

# -----------------------------
# Quiet mode
# -----------------------------

if [[ "$QUIET" != true ]]; then

    gum style \
        --foreground "$BLUE" \
        --border double \
        --border-foreground "$BLUE" \
        --align center \
        --width 64 \
        --padding "1 2" \
        "HASTEBIN UPLOADER" \
        "" \
        "File: $FILE_NAME"

    echo

    gum style \
        --foreground "$TEXT" \
        --border rounded \
        --border-foreground "$MAUVE" \
        --padding "1 2" \
        "File        : $FILE_NAME" \
        "Size        : $FILE_SIZE" \
        "Type        : $FILE_TYPE" \
        "Lines       : $LINE_COUNT"

    echo

fi

# -----------------------------
# Prepare temporary files
# -----------------------------

RESPONSE_FILE=$(mktemp)
PROGRESS_FILE=$(mktemp)

# -----------------------------
# Upload
# -----------------------------

if [[ "$QUIET" == true ]]; then

    if ! curl -fsS \
        -X POST \
        -H "Content-Type: text/plain" \
        --data-binary @"$FILE_PATH" \
        "$UPLOAD_URL" \
        >"$RESPONSE_FILE"; then

        die "Failed to upload the document."
    fi

else

    echo

    gum style \
        --foreground "$CYAN" \
        --padding "0 1" \
        "↑ Uploading $FILE_NAME"

    echo

    # Start curl in the background.
    # Its progress output is written to PROGRESS_FILE.
    curl \
        -fS \
        --progress-bar \
        -X POST \
        -H "Content-Type: text/plain" \
        --data-binary @"$FILE_PATH" \
        "$UPLOAD_URL" \
        >"$RESPONSE_FILE" \
        2>"$PROGRESS_FILE" &

    CURL_PID=$!

    LAST_PERCENT=-1

    while kill -0 "$CURL_PID" 2>/dev/null; do

        # curl writes percentage information using carriage returns.
        # Extract the most recent percentage we can find.
        CURRENT_PERCENT=$(
            tr '\r' '\n' < "$PROGRESS_FILE" 2>/dev/null |
            grep -oE '[0-9]{1,3}(\.[0-9]+)?%' |
            tail -1 |
            tr -d '%' |
            cut -d. -f1
        )

        if [[ -z "$CURRENT_PERCENT" ]]; then
            CURRENT_PERCENT=0
        fi

        if (( CURRENT_PERCENT < 0 )); then
            CURRENT_PERCENT=0
        fi

        if (( CURRENT_PERCENT > 100 )); then
            CURRENT_PERCENT=100
        fi

        if [[ "$CURRENT_PERCENT" != "$LAST_PERCENT" ]]; then

            BAR_WIDTH=40
            FILLED=$(( CURRENT_PERCENT * BAR_WIDTH / 100 ))
            EMPTY=$(( BAR_WIDTH - FILLED ))

            FILLED_BAR=$(printf '%*s' "$FILLED" '' | tr ' ' '█')
            EMPTY_BAR=$(printf '%*s' "$EMPTY" '' | tr ' ' '░')

            PROGRESS_LINE="$FILLED_BAR$EMPTY_BAR"

            # Move cursor to beginning of current line and redraw.
            printf '\r'

            gum style \
                --foreground "$GREEN" \
                --padding "0 1" \
                "[$PROGRESS_LINE] ${CURRENT_PERCENT}%"

            LAST_PERCENT="$CURRENT_PERCENT"
        fi

        sleep 0.1
    done

    wait "$CURL_PID"
    CURL_STATUS=$?

    echo

    if [[ "$CURL_STATUS" -ne 0 ]]; then
        echo
        die "Upload failed."
    fi

    gum spin \
        --spinner points \
        --spinner.foreground "$MAUVE" \
        --title "Processing server response..." \
        -- sleep 0.4

fi

# -----------------------------
# Parse response
# -----------------------------

HASTE_KEY=$(jq -r '.key // empty' "$RESPONSE_FILE" 2>/dev/null)

if [[ -z "$HASTE_KEY" ]]; then
    die "Server returned an invalid response."
fi

URL="$BASE_URL/$HASTE_KEY"

# -----------------------------
# Clipboard
# -----------------------------

COPIED=false

if command -v wl-copy &>/dev/null; then
    printf '%s' "$URL" | wl-copy
    COPIED=true

elif command -v xclip &>/dev/null; then
    printf '%s' "$URL" | xclip -selection clipboard
    COPIED=true

elif command -v xsel &>/dev/null; then
    printf '%s' "$URL" | xsel --clipboard --input
    COPIED=true

elif command -v pbcopy &>/dev/null; then
    printf '%s' "$URL" | pbcopy
    COPIED=true
fi

# -----------------------------
# Save history
# -----------------------------

mkdir -p "$HISTORY_DIR"

TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

printf '%s|%s|%s\n' \
    "$TIMESTAMP" \
    "$FILE_NAME" \
    "$URL" >> "$HISTORY_FILE"

# -----------------------------
# Quiet output
# -----------------------------

if [[ "$QUIET" == true ]]; then
    printf '%s\n' "$URL"
    exit 0
fi

# -----------------------------
# QR code
# -----------------------------

QR_CODE=""

if [[ "$SHOW_QR" == true ]] && command -v qrencode &>/dev/null; then

    QR_CODE=$(
        qrencode \
            -t ANSIUTF8 \
            -m 1 \
            "$URL"
    )

fi

# -----------------------------
# Build result panel
# -----------------------------

STATUS_TEXT="✓ Copied to clipboard"

if [[ "$COPIED" != true ]]; then
    STATUS_TEXT="⚠ Clipboard utility not found"
fi

RESULT_TEXT="File : $FILE_NAME
Size : $FILE_SIZE
Type : $FILE_TYPE
URL  : $URL
     "

if [[ "$COPIED" == true ]]; then
    RESULT_TEXT+="
$STATUS_TEXT"
else
    RESULT_TEXT+="
$STATUS_TEXT"
fi

# -----------------------------
# Result
# -----------------------------

echo

gum style \
    --foreground "$GREEN" \
    --border double \
    --border-foreground "$GREEN" \
    --padding "1 2" \
    --width 64 \
    "Upload Complete" \
    "" \
    "$RESULT_TEXT"

# -----------------------------
# QR
# -----------------------------

if [[ "$SHOW_QR" == true ]]; then

    echo

    if [[ -n "$QR_CODE" ]]; then

        QR_PANEL=$(
            gum style \
                --foreground "$TEXT" \
                --border rounded \
                --border-foreground "$MAUVE" \
                --padding "1 2" \
                --align center \
                "Scan QR Code" \
                "" \
                "$QR_CODE"
        )

        printf '%s\n' "$QR_PANEL"

    else
        warning "qrencode is not installed; QR code skipped."
        gum style \
            --foreground "$YELLOW" \
            --padding "0 1" \
            "Install it with: sudo pacman -S qrencode"
    fi

fi

# -----------------------------
# Actions
# -----------------------------

echo

ACTION=$(
    gum choose \
        --cursor "➜ " \
        --header "What would you like to do?" \
        "Open in browser" \
        "Copy URL again" \
        "Show URL" \
        "Done"
)

case "$ACTION" in

    "Open in browser")

        if command -v xdg-open &>/dev/null; then
            xdg-open "$URL" &>/dev/null &
            success "Opened in browser."

        elif command -v open &>/dev/null; then
            open "$URL" &>/dev/null &
            success "Opened in browser."

        else
            warning "No browser opener found."
        fi
        ;;

    "Copy URL again")

        if command -v wl-copy &>/dev/null; then
            printf '%s' "$URL" | wl-copy
            success "Copied to clipboard."

        elif command -v xclip &>/dev/null; then
            printf '%s' "$URL" | xclip -selection clipboard
            success "Copied to clipboard."

        elif command -v xsel &>/dev/null; then
            printf '%s' "$URL" | xsel --clipboard --input
            success "Copied to clipboard."

        elif command -v pbcopy &>/dev/null; then
            printf '%s' "$URL" | pbcopy
            success "Copied to clipboard."

        else
            warning "No clipboard utility found."
        fi
        ;;

    "Show URL")
        echo
        gum style \
            --foreground "$GREEN" \
            --border rounded \
            --border-foreground "$GREEN" \
            --padding "1 2" \
            "$URL"
        ;;

    "Done"|"")
        ;;
esac

echo

