#!/bin/bash
#
# miaoyan - CLI for MiaoYan Markdown Editor
# https://github.com/tw93/MiaoYan
#

set -e

# Colors
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'

show_banner() {
    printf "${GREEN} __  __ _${NC}\n"
    printf "${GREEN}|  \\/  (_) __ _  ___${NC}\n"
    printf "${GREEN}| |\\/| | |/ _\` |/ _ \\\\${NC}\n"
    printf "${GREEN}| |  | | | (_| | (_) |${NC}  ${BLUE}%s${NC}\n" "https://github.com/tw93/MiaoYan"
    printf "${GREEN}|_|  |_|_|\\__,_|\\___/${NC}   ${GREEN}%s${NC}\n" "Lightweight Markdown app for macOS"
}

cmd_help() {
    show_banner
    echo
    printf "${BLUE}USAGE${NC}\n"
    printf "  miao <command> [options]\n"
    echo
    printf "${BLUE}COMMANDS${NC}\n"
    printf "  ${GREEN}%-24s${NC} %s\n" "list [folder]" "List top-level folders, or markdown in folder"
    printf "  ${GREEN}%-24s${NC} %s\n" "search <query>" "Search notes in terminal"
    printf "  ${GREEN}%-24s${NC} %s\n" "open <title|path>" "Open note"
    printf "  ${GREEN}%-24s${NC} %s\n" "cat <title|path>" "Print note content"
    printf "  ${GREEN}%-24s${NC} %s\n" "new <title> [text]" "Create new note"
    printf "  ${GREEN}%-24s${NC} %s\n" "update" "Update to latest version"
    printf "  ${GREEN}%-24s${NC} %s\n" "help" "Show this help"
    echo
}

# Handle help before path detection
case "${1:-help}" in
    help|--help|-h) cmd_help; exit 0 ;;
esac

# Auto-detect notes path from app preferences, fallback to common locations
normalize_path() {
    local path="$1"

    [[ -z "$path" ]] && return

    # defaults may wrap string values with quotes when spaces are present
    path="${path#\"}"
    path="${path%\"}"

    # Handle file URLs from preferences
    if [[ "$path" == file://* ]]; then
        path="${path#file://}"
        path=$(printf '%b' "${path//%/\\x}")
    fi

    case "$path" in
        "~") path="$HOME" ;;
        "~/"*) path="$HOME/${path#~/}" ;;
    esac

    echo "$path"
}

read_pref_path() {
    local domain="$1"
    local key="$2"
    local raw_path
    local path

    raw_path=$(defaults read "$domain" "$key" 2>/dev/null || true)
    path=$(normalize_path "$raw_path")

    if [[ -n "$path" && -d "$path" ]]; then
        echo "$path"
    fi
}

detect_path() {
    local pref_path

    # MiaoYan 2.7+ setting key
    pref_path=$(read_pref_path "com.tw93.miaoyan" "storageUrl")
    if [[ -n "$pref_path" ]]; then
        echo "$pref_path"
        return
    fi
    
    # Common default locations
    for p in "$HOME/Documents/MiaoYan" "$HOME/Save/MiaoYan" "$HOME/MiaoYan"; do
        [[ -d "$p" ]] && echo "$p" && return
    done
    
    echo ""
}

NOTES_PATH="${MIAOYAN_PATH:-$(detect_path)}"

if [[ -z "$NOTES_PATH" || ! -d "$NOTES_PATH" ]]; then
    echo "Error: Notes directory not found." >&2
    echo "Set MIAOYAN_PATH or configure in MiaoYan preferences." >&2
    exit 1
fi

# URL encode helper
urlencode() {
    python3 -c "import urllib.parse; print(urllib.parse.quote('''$1''', safe=''))"
}

# Find note file by title (searches recursively, excludes Trash)
find_note() {
    local title="${1%.md}"
    find "$NOTES_PATH" -name "*.md" -not -path "*/Trash/*" | while read -r f; do
        basename="${f##*/}"
        name="${basename%.md}"
        [[ "$name" == "$title" ]] && echo "$f" && return
    done
}

resolve_note_path() {
    local arg="$1"
    local candidate
    local note

    # Explicit path from current directory or absolute path
    if [[ -f "$arg" ]]; then
        echo "$arg"
        return
    fi

    # Resolve relative paths against notes root
    if [[ "$arg" != /* ]]; then
        candidate="$NOTES_PATH/${arg#./}"
        if [[ -f "$candidate" ]]; then
            echo "$candidate"
            return
        fi
        if [[ "$candidate" != *.md && -f "$candidate.md" ]]; then
            echo "$candidate.md"
            return
        fi
    elif [[ "$arg" != *.md && -f "$arg.md" ]]; then
        echo "$arg.md"
        return
    fi

    # Fallback to exact title match
    note=$(find_note "$arg")
    if [[ -n "$note" ]]; then
        echo "$note"
    fi
}

# Commands
cmd_list() {
    local folder="$1"
    local search_path="$NOTES_PATH"
    local rel_path
    local has_root_notes=0
    
    if [[ -n "$folder" ]]; then
        search_path="$NOTES_PATH/${folder%/}"
        if [[ ! -d "$search_path" ]]; then
            echo "Folder not found: $folder" >&2
            exit 1
        fi

        find "$search_path" -type f -name "*.md" -not -path "*/Trash/*" | while read -r f; do
            rel_path="${f#$search_path/}"
            [[ "$rel_path" == */* ]] && continue
            # Keep output relative to notes root
            echo "${f#$NOTES_PATH/}"
        done | sort
        return
    fi
    
    find "$search_path" -mindepth 1 -maxdepth 1 -type d -not -name "Trash" -not -name ".*" | while read -r d; do
        # Only show top-level folders that actually contain markdown notes.
        if find "$d" -type f -name "*.md" -not -path "*/Trash/*" -print -quit | grep -q .; then
            echo "${d#$NOTES_PATH/}"
        fi
    done | sort

    if find "$search_path" -maxdepth 1 -type f -name "*.md" -print -quit | grep -q .; then
        has_root_notes=1
    fi

    if [[ "$has_root_notes" -eq 1 ]]; then
        echo "Tip: root notes are hidden in default list. Run 'miao list .' to show them." >&2
    fi
}

cmd_search() {
    local query="$1"
    local tmp_file
    [[ -z "$query" ]] && echo "Usage: miaoyan search <query>" >&2 && exit 1

    tmp_file=$(mktemp)

    if command -v rg >/dev/null 2>&1; then
        rg -n --no-heading --color never -F --glob "*.md" --glob "!**/Trash/**" -- "$query" "$NOTES_PATH" >"$tmp_file" || true
    else
        find "$NOTES_PATH" -type f -name "*.md" -not -path "*/Trash/*" -exec grep -nH -- "$query" {} + >"$tmp_file" 2>/dev/null || true
    fi

    if [[ ! -s "$tmp_file" ]]; then
        rm -f "$tmp_file"
        echo "No matches found: $query" >&2
        exit 1
    fi

    while IFS= read -r line; do
        echo "${line#$NOTES_PATH/}"
    done <"$tmp_file"

    rm -f "$tmp_file"
}

cmd_open() {
    local arg="$1"
    local file
    [[ -z "$arg" ]] && echo "Usage: miaoyan open <title|path>" >&2 && exit 1

    # Prefer opening a resolved file path to enter single mode
    file=$(resolve_note_path "$arg")
    if [[ -n "$file" ]]; then
        open -a MiaoYan "$file"
        return
    fi

    # Fallback to title route (strip optional .md suffix)
    open "miaoyan://goto/$(urlencode "${arg%.md}")"
}

cmd_new() {
    local title="$1"
    local text="${2:-}"
    [[ -z "$title" ]] && echo "Usage: miaoyan new <title> [text]" >&2 && exit 1
    
    local url="miaoyan://new/?title=$(urlencode "$title")"
    [[ -n "$text" ]] && url="$url&txt=$(urlencode "$text")"
    open "$url"
}

cmd_cat() {
    local arg="$1"
    local file
    [[ -z "$arg" ]] && echo "Usage: miaoyan cat <title|path>" >&2 && exit 1

    file=$(resolve_note_path "$arg")

    if [[ -z "$file" ]]; then
        echo "Note not found: $arg" >&2
        exit 1
    fi

    cat "$file"
}

cmd_update() {
    local script_path
    script_path="$(command -v miao 2>/dev/null || echo "$0")"
    local tmp_file
    tmp_file=$(mktemp)

    printf "${GREEN}▸${NC} Checking for updates...\n"

    if ! curl -fsSL "https://raw.githubusercontent.com/tw93/MiaoYan/main/scripts/miaoyan" -o "$tmp_file" 2>/dev/null; then
        rm -f "$tmp_file"
        echo "Error: Failed to download update." >&2
        exit 1
    fi

    chmod +x "$tmp_file"
    mv "$tmp_file" "$script_path" 2>/dev/null || {
        sudo mv "$tmp_file" "$script_path" || {
            rm -f "$tmp_file"
            echo "Error: Failed to install update." >&2
            exit 1
        }
    }

    printf "${GREEN}▸${NC} Updated successfully!\n"
}

# Main
case "$1" in
    list)    cmd_list "$2" ;;
    search)  cmd_search "$2" ;;
    open)    cmd_open "$2" ;;
    new)     cmd_new "$2" "$3" ;;
    cat)     cmd_cat "$2" ;;
    update)  cmd_update ;;
    *)
        echo "Unknown command: $1" >&2
        echo "Run 'miaoyan help' for usage." >&2
        exit 1
        ;;
esac
