#!/bin/bash
# Merge worktree to main with locking, then cleanup
# Usage: ./workflow/finish <name>

set -e

NAME="$1"
WORKTREE_BASE="worktrees"
LOCK_FILE=".workflow-merge.lock"
LOCK_TIMEOUT=30
MAX_RETRIES=10

if [[ -z "$NAME" ]]; then
    echo "Usage: ./workflow/finish <name>"
    echo ""
    ./workflow/status
    exit 1
fi

# Find worktree
WORKTREE_PATH=$(find "$WORKTREE_BASE" -mindepth 2 -maxdepth 2 -type d -name "$NAME" 2>/dev/null | head -1)

if [[ -z "$WORKTREE_PATH" ]]; then
    echo "Error: Worktree '$NAME' not found"
    exit 1
fi

BRANCH="work/$NAME"

# Verify this is a proper git worktree (has .git file, not fake worktree)
if [[ ! -f "$WORKTREE_PATH/.git" ]]; then
    echo "Error: '$WORKTREE_PATH' is not a valid git worktree"
    echo "(Missing .git file - may be a legacy directory, not created via ./workflow/start)"
    exit 1
fi

# Check for uncommitted changes
if [[ -n $(git -C "$WORKTREE_PATH" status --porcelain) ]]; then
    echo "Error: Worktree has uncommitted changes"
    git -C "$WORKTREE_PATH" status --short
    exit 1
fi

# Check for blockers
if [[ -f "$WORKTREE_PATH/STATUS.md" ]]; then
    BLOCKED=$(grep "^blocked:" "$WORKTREE_PATH/STATUS.md" 2>/dev/null | cut -d: -f2 | tr -d ' ')
    if [[ "$BLOCKED" == "true" ]]; then
        REASON=$(grep "^blocker_reason:" "$WORKTREE_PATH/STATUS.md" | cut -d: -f2-)
        echo "Error: Worktree is blocked"
        echo "Reason: $REASON"
        echo ""
        echo "Run './workflow/unblock $NAME' first if blocker is resolved."
        exit 1
    fi
fi

COMMITS_AHEAD=$(git -C "$WORKTREE_PATH" rev-list --count main..HEAD 2>/dev/null || echo "0")
echo "Commits to merge: $COMMITS_AHEAD"

if [[ "$COMMITS_AHEAD" -eq 0 ]]; then
    echo "Warning: No commits to merge. Use 'abandon' instead?"
    read -p "Continue anyway? [y/N] " -n 1 -r
    echo
    [[ $REPLY =~ ^[Yy]$ ]] || exit 1
fi

# Acquire lock with retry
acquire_lock() {
    local retry=0
    while [[ $retry -lt $MAX_RETRIES ]]; do
        if mkdir "$LOCK_FILE" 2>/dev/null; then
            echo $$ > "$LOCK_FILE/pid"
            echo "$NAME" > "$LOCK_FILE/worktree"
            trap 'rm -rf "$LOCK_FILE"' EXIT
            return 0
        fi

        # Check if lock is stale (older than 5 minutes)
        if [[ -f "$LOCK_FILE/pid" ]]; then
            LOCK_AGE=$(( $(date +%s) - $(stat -c %Y "$LOCK_FILE/pid" 2>/dev/null || echo 0) ))
            if [[ $LOCK_AGE -gt 300 ]]; then
                echo "Removing stale lock (age: ${LOCK_AGE}s)"
                rm -rf "$LOCK_FILE"
                continue
            fi

            LOCK_HOLDER=$(cat "$LOCK_FILE/worktree" 2>/dev/null || echo "unknown")
            echo "Waiting for lock (held by: $LOCK_HOLDER)... retry $((retry + 1))/$MAX_RETRIES"
        fi

        sleep $LOCK_TIMEOUT
        ((retry++))
    done

    echo "Error: Could not acquire merge lock after $MAX_RETRIES attempts"
    exit 1
}

echo ""
echo "Acquiring merge lock..."
acquire_lock
echo "Lock acquired."

# Merge to main
echo ""
echo "Merging $BRANCH to main..."
cd codebase
git fetch origin main 2>/dev/null || true
git checkout main
git pull origin main 2>/dev/null || true

# Get last commit message for merge commit
LAST_MSG=$(git -C "../$WORKTREE_PATH" log -1 --format=%s 2>/dev/null || echo "completed")
git merge --no-ff "$BRANCH" -m "Merge $NAME: $LAST_MSG"

# Increment version
echo ""
NEW_VERSION=$("$(dirname "$0")/version" merge "$NAME")
echo "Version: $NEW_VERSION"
git add VERSION.json
git commit --amend --no-edit
cd ..

# Archive HANDOFF.md to project/history/
HISTORY_DIR="project/history"
TODAY=$(date +%Y%m%d)
mkdir -p "$HISTORY_DIR"

if [[ -f "$WORKTREE_PATH/HANDOFF.md" ]]; then
    ARCHIVE_FILE="$HISTORY_DIR/${TODAY}-${NAME}.md"
    echo "Archiving HANDOFF.md to $ARCHIVE_FILE"

    # Add completion header to archived file
    {
        echo "# $NAME (Completed)"
        echo ""
        echo "**Merged**: $(date -Iseconds)"
        echo "**Commits**: $COMMITS_AHEAD"
        echo ""
        echo "---"
        echo ""
        cat "$WORKTREE_PATH/HANDOFF.md"
    } > "$ARCHIVE_FILE"

    cd codebase
    git add "../$ARCHIVE_FILE"
    git commit -m "archive: $NAME completion record" 2>/dev/null || true
    cd ..
fi

# Cleanup
echo "Cleaning up..."
git -C codebase worktree remove "../$WORKTREE_PATH" --force
git -C codebase branch -d "$BRANCH" 2>/dev/null || git -C codebase branch -D "$BRANCH"

# Remove dated directory if empty
DATED_DIR=$(dirname "$WORKTREE_PATH")
rmdir "$DATED_DIR" 2>/dev/null || true

# Refresh symlinks
"$(dirname "$0")/refresh"

echo ""
echo "Done! $NAME merged to main and cleaned up."
echo ""
echo "Push to origin:"
echo "  git push origin main"
