#!/bin/bash
# Toggle dictation: ⌘⇧D / Fn → запись с микрофона; повторное нажатие → Groq Whisper → текст в /tmp/groq-dictate.last
# Hammerspoon Lua callback вставляет через hs.eventtap.keyStroke({"cmd"},"v") в активное окно.
# Fallback: если Groq недоступен (нет сети / 429 / 5xx) → локальный whisper-cli (whisper-cpp tiny ru).

# Hammerspoon при автозапуске даёт пустой PATH — добавляем явно (Intel + Apple Silicon brew пути)
export PATH="/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"

PID_FILE="/tmp/groq-dictate.pid"
WAV_FILE="/tmp/groq-dictate.wav"
WAV_16K="/tmp/groq-dictate-16k.wav"
OUT_FILE="/tmp/groq-dictate.last"
LOG="/tmp/groq-dictate.log"
GROQ_KEY="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"
WHISPER_MODEL="$HOME/.cache/whisper-cpp/ggml-tiny-q5_1.bin"

log() { echo "[$(date +%H:%M:%S)] $*" >> "$LOG"; }
notify() { osascript -e "display notification \"$1\" with title \"Groq Dictate\""; }

groq_transcribe() {
    local response
    response=$(curl -sS -X POST "https://api.groq.com/openai/v1/audio/transcriptions" \
        -H "Authorization: Bearer $GROQ_KEY" \
        -F "file=@$WAV_FILE" \
        -F "model=whisper-large-v3-turbo" \
        -F "language=ru" \
        -F "response_format=json" \
        --max-time 15 2>/dev/null) || return 1
    local code
    code=$(echo "$response" | jq -r '.error.code // empty' 2>/dev/null)
    [ -n "$code" ] && { log "Groq error: $response"; return 1; }
    echo "$response" | jq -r '.text // empty' 2>/dev/null | sed 's/^ *//;s/ *$//'
}

local_transcribe() {
    [ ! -f "$WHISPER_MODEL" ] && { log "no local model: $WHISPER_MODEL"; return 1; }
    ffmpeg -hide_banner -loglevel error -i "$WAV_FILE" -ar 16000 -ac 1 -y "$WAV_16K" 2>>"$LOG" || return 1
    whisper-cli -m "$WHISPER_MODEL" -l ru -nt -np "$WAV_16K" 2>>"$LOG" | sed 's/^ *//;s/ *$//' | tr -d '\n'
}

if [ -f "$PID_FILE" ]; then
    # === STOP & TRANSCRIBE ===
    PID=$(cat "$PID_FILE")
    log "STOP pid=$PID"
    kill -INT "$PID" 2>/dev/null
    for i in 1 2 3 4 5; do kill -0 "$PID" 2>/dev/null || break; sleep 0.1; done
    rm -f "$PID_FILE"

    if [ ! -s "$WAV_FILE" ]; then
        log "ERR empty wav"; notify "Запись пустая"; exit 1
    fi

    log "POST size=$(stat -f%z "$WAV_FILE")B"
    TEXT=$(groq_transcribe)
    if [ -z "$TEXT" ]; then
        log "Groq fail → trying local whisper-cli"
        notify "☁️→💻 Groq не отвечает, локальная модель"
        TEXT=$(local_transcribe)
        [ -z "$TEXT" ] && { log "Local also empty"; notify "Не распознано"; exit 1; }
        log "LOCAL DONE: $TEXT"
    else
        log "GROQ DONE: $TEXT"
    fi

    printf '%s' "$TEXT" > "$OUT_FILE"
else
    # === START RECORDING ===
    rm -f "$WAV_FILE" "$WAV_16K" "$OUT_FILE"
    log "START → $WAV_FILE"
    ffmpeg -hide_banner -loglevel error -f avfoundation -i ":0" -ar 16000 -ac 1 -y "$WAV_FILE" >/dev/null 2>>"$LOG" &
    echo $! > "$PID_FILE"
    notify "🎙️ Говори"
fi
