#!/bin/bash
# rivet.sh - Minimal COO system for RateRight
# One script. No framework. Just works.
# Uses GitHub as external memory/coordination layer.

set -euo pipefail

# === CONFIG ===
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RIVET_DIR="$(dirname "$SCRIPT_DIR")"
REPO_DIR="$(dirname "$RIVET_DIR")"

# Load secrets
source /root/.rivet.env

# Paths - Rivet's brain
SOUL="$RIVET_DIR/SOUL.md"
IDENTITY="$RIVET_DIR/IDENTITY.md"
USER_MD="$RIVET_DIR/USER.md"
CONTEXT="$RIVET_DIR/CONTEXT.md"
MEMORY="$RIVET_DIR/MEMORY.md"
HEARTBEAT="$RIVET_DIR/HEARTBEAT.md"
LOG_FILE="$RIVET_DIR/logs/$(date +%Y-%m-%d).log"

# Paths - CC coordination
CLAUDE_DIR="$REPO_DIR/.claude"
CC_INBOX="$CLAUDE_DIR/INBOX.md"
CC_OUTBOX="$CLAUDE_DIR/OUTBOX.md"
CC_STATUS="$CLAUDE_DIR/STATUS.md"

# Telegram
TG_API="https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}"
LAST_UPDATE_FILE="/tmp/rivet_last_update"

# Git sync timing
LAST_PULL_FILE="/tmp/rivet_last_pull"
PULL_INTERVAL=300  # 5 minutes
PENDING_PUSH=false

# === LOGGING ===
log() {
    mkdir -p "$(dirname "$LOG_FILE")"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# === GIT SYNC (SMART) ===
git_pull_if_needed() {
    local now=$(date +%s)
    local last_pull=0

    if [[ -f "$LAST_PULL_FILE" ]]; then
        last_pull=$(cat "$LAST_PULL_FILE")
    fi

    local elapsed=$((now - last_pull))

    if [[ $elapsed -ge $PULL_INTERVAL ]]; then
        log "Git pull (${elapsed}s since last)..."
        cd "$REPO_DIR"
        git pull --rebase origin main 2>/dev/null || git pull origin main 2>/dev/null || true
        echo "$now" > "$LAST_PULL_FILE"
    fi
}

git_pull_now() {
    log "Git pull (forced)..."
    cd "$REPO_DIR"
    git pull --rebase origin main 2>/dev/null || git pull origin main 2>/dev/null || true
    echo "$(date +%s)" > "$LAST_PULL_FILE"
}

git_push_async() {
    local message="${1:-rivet: auto-update}"

    # Run in background, don't block
    (
        cd "$REPO_DIR"
        git add -A

        if git diff --cached --quiet; then
            exit 0  # Nothing to push
        fi

        git commit -m "$message" 2>/dev/null || true
        git push origin main 2>/dev/null || log "Push failed - will retry"
    ) &
}

git_push_now() {
    local message="${1:-rivet: auto-update}"
    cd "$REPO_DIR"
    git add -A

    if git diff --cached --quiet; then
        log "Nothing to commit"
        return 0
    fi

    git commit -m "$message" || true
    git push origin main || log "Push failed"
}

# === CC COORDINATION ===
cc_status() {
    if [[ -f "$CC_STATUS" ]]; then
        if grep -q "🟡 WORKING\|🔵 Working\|in_progress" "$CC_STATUS" 2>/dev/null; then
            echo "working"
        elif grep -q "🔴\|ERROR\|error" "$CC_STATUS" 2>/dev/null; then
            echo "error"
        else
            echo "idle"
        fi
    else
        echo "unknown"
    fi
}

cc_check_outbox() {
    if [[ -f "$CC_OUTBOX" ]]; then
        grep -E "^\*\*[0-9]{4}-[0-9]{2}-[0-9]{2}" "$CC_OUTBOX" | head -1 || echo ""
    fi
}

cc_assign_task() {
    local task_type="$1"
    local description="$2"
    local priority="${3:-NORMAL}"
    local task_id="TASK-$(date +%Y%m%d-%H%M%S)"

    log "Assigning task to CC: $task_id"

    # Read current INBOX
    local current=""
    if [[ -f "$CC_INBOX" ]]; then
        current=$(cat "$CC_INBOX")
    fi

    # Add task to PENDING section
    cat > "$CC_INBOX" << EOF
# CC INBOX

Tasks for Claude Code. Rivet adds tasks here, CC picks them up.

## PENDING

### $task_id
- **Type:** $task_type
- **Priority:** $priority
- **Description:** $description
- **Assigned:** $(date -u '+%Y-%m-%d %H:%M UTC')
- **From:** Rivet

## IN PROGRESS

## DONE

$(echo "$current" | grep -A 1000 "^## DONE" | tail -n +2 || echo "")
EOF

    # Push async - don't block
    git_push_async "rivet: assigned $task_id to CC"
    log "Task $task_id assigned"
    echo "$task_id"
}

# === MEMORY UPDATES ===
memory_learn() {
    local category="$1"
    local lesson="$2"

    log "Learning: $lesson"

    local today=$(date '+%Y-%m-%d')

    case "$category" in
        technical)
            sed -i "/^## Technical Patterns/a - $lesson ($today)" "$MEMORY" 2>/dev/null || \
            echo -e "\n- $lesson ($today)" >> "$MEMORY"
            ;;
        michael)
            sed -i "/^## About Michael/a - $lesson ($today)" "$MEMORY" 2>/dev/null || \
            echo -e "\n- $lesson ($today)" >> "$MEMORY"
            ;;
        mistake)
            echo "| $today | $lesson | (pending) |" >> "$MEMORY"
            ;;
        *)
            echo -e "\n- $lesson ($today)" >> "$MEMORY"
            ;;
    esac

    # Push async
    git_push_async "rivet: learned - $lesson"
}

# === TELEGRAM ===
tg_send() {
    local chat_id="$1"
    local text="$2"

    # Telegram has 4096 char limit
    if [[ ${#text} -gt 4000 ]]; then
        text="${text:0:4000}..."
    fi

    curl -s -X POST "$TG_API/sendMessage" \
        -d "chat_id=$chat_id" \
        -d "text=$text" \
        -d "parse_mode=Markdown" > /dev/null 2>&1 || \
    curl -s -X POST "$TG_API/sendMessage" \
        -d "chat_id=$chat_id" \
        -d "text=$text" > /dev/null
}

tg_get_updates() {
    local offset="${1:-0}"
    curl -s "$TG_API/getUpdates?offset=$offset&timeout=30"
}

# === WHISPER ===
transcribe_voice() {
    local file_id="$1"

    local file_path
    file_path=$(curl -s "$TG_API/getFile?file_id=$file_id" | jq -r '.result.file_path')

    curl -s "https://api.telegram.org/file/bot${TELEGRAM_BOT_TOKEN}/$file_path" -o /tmp/voice.ogg

    curl -s https://api.openai.com/v1/audio/transcriptions \
        -H "Authorization: Bearer $OPENAI_API_KEY" \
        -F file=@/tmp/voice.ogg \
        -F model=whisper-1 \
        -F language=en | jq -r '.text'
}

# === CLAUDE OPUS 4.5 ===
think() {
    local user_message="$1"

    # Build context from MD files
    local context=""
    context+="# SOUL\n$(cat "$SOUL")\n\n"
    context+="# IDENTITY\n$(cat "$IDENTITY")\n\n"
    context+="# USER\n$(cat "$USER_MD")\n\n"
    context+="# CONTEXT\n$(cat "$CONTEXT")\n\n"
    context+="# MEMORY\n$(cat "$MEMORY")\n\n"

    # Add CC status
    context+="\n# CC STATUS\n"
    context+="Claude Code is currently: $(cc_status)\n"
    if [[ -f "$CC_OUTBOX" ]]; then
        context+="Latest from CC:\n$(tail -20 "$CC_OUTBOX")\n"
    fi

    local response
    response=$(curl -s https://api.anthropic.com/v1/messages \
        -H "Content-Type: application/json" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -d "$(jq -n \
            --arg context "$context" \
            --arg msg "$user_message" \
            '{
                model: "claude-opus-4-5-20251101",
                max_tokens: 1024,
                system: $context,
                messages: [
                    {role: "user", content: $msg}
                ]
            }')")

    echo "$response" | jq -r '.content[0].text // "Error: No response"'
}

# === COMMANDS ===
handle_command() {
    local cmd="$1"
    local args="${2:-}"
    local chat_id="$3"

    case "$cmd" in
        /start|/help)
            tg_send "$chat_id" "🔧 *Rivet Online*

/status - System health
/cc - CC status
/task <desc> - Assign to CC
/bug <desc> - Assign bug (high priority)
/health - Health check
/brief - Status brief
/learn <lesson> - Save to memory
/sync - Force git sync

Or just talk to me."
            ;;
        /status)
            local status="🔧 *Rivet Status*\n\n"
            status+="📍 VPS: $(hostname)\n"
            status+="💾 Disk: $(df -h / | awk 'NR==2 {print $5}')\n"
            status+="🧠 Memory: $(free -m | awk 'NR==2 {printf "%.0f%%", $3/$2*100}')\n"
            status+="\n*CC:* $(cc_status)"
            tg_send "$chat_id" "$status"
            ;;
        /cc)
            local cc_info="🤖 *Claude Code*\n\n"
            cc_info+="*Status:* $(cc_status)\n\n"
            cc_info+="*Recent Output:*\n"
            if [[ -f "$CC_OUTBOX" ]]; then
                cc_info+="$(tail -10 "$CC_OUTBOX")"
            else
                cc_info+="(no output yet)"
            fi
            tg_send "$chat_id" "$cc_info"
            ;;
        /task)
            if [[ -z "$args" ]]; then
                tg_send "$chat_id" "Usage: /task <description>"
                return 0
            fi
            local task_id
            task_id=$(cc_assign_task "task" "$args" "NORMAL")
            tg_send "$chat_id" "✅ Assigned: $task_id"
            ;;
        /bug)
            if [[ -z "$args" ]]; then
                tg_send "$chat_id" "Usage: /bug <description>"
                return 0
            fi
            local task_id
            task_id=$(cc_assign_task "bug" "$args" "HIGH")
            tg_send "$chat_id" "🐛 Bug assigned: $task_id"
            ;;
        /brief)
            tg_send "$chat_id" "🤔..."
            local brief
            brief=$(think "Give me a concise status brief (max 500 chars). Current state, what needs attention, CC status.")
            tg_send "$chat_id" "$brief"
            ;;
        /health)
            local ge_status="❌"
            if curl -s -o /dev/null -w "%{http_code}" "${GROWTH_ENGINE_URL}/api/health" 2>/dev/null | grep -q "200"; then
                ge_status="✅"
            fi

            local rr_status="❌"
            if curl -s -o /dev/null -w "%{http_code}" "https://app.rateright.com.au" 2>/dev/null | grep -q "200"; then
                rr_status="✅"
            fi

            tg_send "$chat_id" "*Health*
$ge_status Growth Engine
$rr_status RateRight
🟢 Rivet
🔵 CC: $(cc_status)"
            ;;
        /learn)
            if [[ -z "$args" ]]; then
                tg_send "$chat_id" "Usage: /learn <lesson>"
                return 0
            fi
            memory_learn "general" "$args"
            tg_send "$chat_id" "📝 Learned."
            ;;
        /sync)
            tg_send "$chat_id" "🔄 Syncing..."
            git_pull_now
            git_push_now "rivet: manual sync"
            tg_send "$chat_id" "✅ Synced"
            ;;
        *)
            return 1
            ;;
    esac
    return 0
}

# === MESSAGE HANDLER ===
handle_message() {
    local update="$1"

    local chat_id=$(echo "$update" | jq -r '.message.chat.id')
    local from_id=$(echo "$update" | jq -r '.message.from.id')
    local text=$(echo "$update" | jq -r '.message.text // empty')
    local voice_id=$(echo "$update" | jq -r '.message.voice.file_id // empty')

    # Only respond to Michael
    if [[ "$from_id" != "$TELEGRAM_CHAT_ID" ]]; then
        log "Ignored: $from_id"
        return
    fi

    # Voice messages
    if [[ -n "$voice_id" ]]; then
        log "Voice message..."
        tg_send "$chat_id" "🎤..."
        text=$(transcribe_voice "$voice_id")
        log "Transcribed: $text"
        tg_send "$chat_id" "📝 _${text}_"
    fi

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

    log "Michael: $text"

    # Commands
    if [[ "$text" == /* ]]; then
        local cmd=$(echo "$text" | awk '{print $1}')
        local args=$(echo "$text" | cut -d' ' -f2- | sed 's/^[[:space:]]*//')
        [[ "$args" == "$cmd" ]] && args=""

        if handle_command "$cmd" "$args" "$chat_id"; then
            return
        fi
    fi

    # Regular message
    tg_send "$chat_id" "🤔..."
    local response
    response=$(think "$text")
    tg_send "$chat_id" "$response"
    log "Responded"
}

# === POLLING LOOP ===
run_polling() {
    log "=== Rivet starting ==="
    log "Repo: $REPO_DIR"

    # Initial pull
    git_pull_now

    log "CC Status: $(cc_status)"

    # Get last update ID
    local offset=0
    if [[ -f "$LAST_UPDATE_FILE" ]]; then
        offset=$(cat "$LAST_UPDATE_FILE")
    fi

    # Send startup message
    tg_send "$TELEGRAM_CHAT_ID" "🔧 Rivet online"

    while true; do
        # Smart pull - only every 5 min
        git_pull_if_needed

        # Get updates (30s long poll)
        local updates
        updates=$(tg_get_updates "$offset")

        # Process each update
        echo "$updates" | jq -c '.result[]?' 2>/dev/null | while read -r update; do
            local update_id=$(echo "$update" | jq -r '.update_id')

            handle_message "$update" || true

            offset=$((update_id + 1))
            echo "$offset" > "$LAST_UPDATE_FILE"
        done
    done
}

# === ONE-SHOT MODE ===
run_once() {
    local action="$1"

    # Pull first
    git_pull_now

    case "$action" in
        morning-brief)
            log "Morning brief..."
            local brief
            brief=$(think "Generate the morning brief per HEARTBEAT.md. Include: system status, CC status, pipeline, overnight activity, decisions needed, priorities. Be concise.")
            tg_send "$TELEGRAM_CHAT_ID" "☀️ *Morning Brief*

$brief"
            log "Sent"
            ;;
        evening-brief)
            log "Evening brief..."
            local brief
            brief=$(think "Generate the evening brief per HEARTBEAT.md. Include: today's results, what got done, what's in progress, what's blocked, overnight plan.")
            tg_send "$TELEGRAM_CHAT_ID" "🌙 *Evening Brief*

$brief"
            log "Sent"
            ;;
        health-check)
            local ge_code
            ge_code=$(curl -s -o /dev/null -w "%{http_code}" "${GROWTH_ENGINE_URL}/api/health" 2>/dev/null || echo "000")

            if [[ "$ge_code" != "200" ]]; then
                tg_send "$TELEGRAM_CHAT_ID" "🚨 Growth Engine: $ge_code"
                log "ALERT: GE $ge_code"
            fi

            local cc=$(cc_status)
            if [[ "$cc" == "error" ]]; then
                tg_send "$TELEGRAM_CHAT_ID" "🚨 CC error state"
                log "ALERT: CC error"
            fi

            log "Health OK (GE: $ge_code, CC: $cc)"
            ;;
        sync)
            git_push_now "rivet: scheduled sync"
            log "Synced"
            ;;
        *)
            echo "Usage: rivet.sh [polling|morning-brief|evening-brief|health-check|sync]"
            exit 1
            ;;
    esac
}

# === ENTRY POINT ===
mkdir -p "$RIVET_DIR/logs"

case "${1:-polling}" in
    polling)
        run_polling
        ;;
    *)
        run_once "$1"
        ;;
esac
