#!/usr/bin/env bash
# context-load — Gather project context for a Claude Code session
#
# Walks from cwd upward collecting key index files.
# Outputs structured context to stdout, suitable for --append-system-prompt.
#
# What it loads:
#   - Every CLAUDE.md found walking up from cwd (top-down order)
#   - Directory tree (depth 3) from each CLAUDE.md location
#   - Every CONTEXT.md found walking up from cwd (top-down order)
#   - Every MEMORY.md found walking up from cwd (top-down order)
#   - Every BESTPRACTICES.md found walking up from cwd (top-down order)
#   - All *.md files in cwd
#   - git-status-report from the highest-level CLAUDE.md dir
set -uo pipefail

TREE_DEPTH=3

# --- Helpers ---

emit_header() {
    echo ""
    echo "================================================================"
    echo "=== $1"
    echo "================================================================"
    echo ""
}

emit_file() {
    local filepath="$1"
    emit_header "FILE: $filepath"
    cat "$filepath"
    echo ""
}

emit_tree() {
    local dir="$1"
    emit_header "TREE: $dir (depth $TREE_DEPTH)"
    tree -L "$TREE_DEPTH" --charset utf-8 -I '.git|node_modules|__pycache__|.venv|venv|customers' "$dir" 2>/dev/null \
        || find "$dir" -maxdepth "$TREE_DEPTH" -not -path '*/.git/*' -not -path '*/.git' -not -path '*/customers/*' -not -path '*/customers' | sort
    echo ""
}

strip_ansi() {
    sed 's/\x1b\[[0-9;]*m//g'
}

# --- Discovery: walk from cwd upward ---

discover_upward() {
    local dir="$PWD"
    local dirs=()
    while [[ "$dir" != "/" ]]; do
        dirs+=("$dir")
        dir="$(dirname "$dir")"
    done
    # Return in top-down order (reverse — highest ancestor first)
    for ((i=${#dirs[@]}-1; i>=0; i--)); do
        echo "${dirs[$i]}"
    done
}

# Collect dirs that have key index files
claude_dirs=()
context_dirs=()
memory_dirs=()
bestpractices_dirs=()
all_hierarchy_dirs=()

while IFS= read -r dir; do
    all_hierarchy_dirs+=("$dir")
    [[ -f "$dir/CLAUDE.md" ]] && claude_dirs+=("$dir")
    [[ -f "$dir/CONTEXT.md" ]] && context_dirs+=("$dir")
    [[ -f "$dir/MEMORY.md" ]] && memory_dirs+=("$dir")
    [[ -f "$dir/BESTPRACTICES.md" ]] && bestpractices_dirs+=("$dir")
done < <(discover_upward)

if [[ ${#claude_dirs[@]} -eq 0 ]]; then
    echo "# No CLAUDE.md found in directory hierarchy" >&2
    echo "# Searched from: $PWD" >&2
fi

# --- Output: Claude profile ---

profile_dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
profile_name="$(basename "$profile_dir")"
if [[ "$profile_name" == ".claude" ]]; then
    emit_header "CLAUDE PROFILE: default (~/.claude)"
else
    emit_header "CLAUDE PROFILE: $profile_name ($profile_dir)"
fi

# --- Output: CLAUDE.md files (top-down) + tree from each ---

# Track files we've already emitted to avoid duplicates
declare -A emitted_files

for dir in "${claude_dirs[@]}"; do
    # Resolve symlinks for dedup — two paths might point to the same file
    real_path="$(readlink -f "$dir/CLAUDE.md")"
    if [[ -z "${emitted_files[$real_path]:-}" ]]; then
        emit_file "$dir/CLAUDE.md"
        emitted_files["$real_path"]=1
    fi
    emit_tree "$dir"
done

# --- Output: CONTEXT.md files (top-down) ---

for dir in "${context_dirs[@]}"; do
    real_path="$(readlink -f "$dir/CONTEXT.md")"
    if [[ -z "${emitted_files[$real_path]:-}" ]]; then
        emit_file "$dir/CONTEXT.md"
        emitted_files["$real_path"]=1
    fi
done

# --- Output: MEMORY.md files (top-down) ---

for dir in "${memory_dirs[@]}"; do
    real_path="$(readlink -f "$dir/MEMORY.md")"
    if [[ -z "${emitted_files[$real_path]:-}" ]]; then
        emit_file "$dir/MEMORY.md"
        emitted_files["$real_path"]=1
    fi
done

# --- Output: BESTPRACTICES.md files (top-down) ---

for dir in "${bestpractices_dirs[@]}"; do
    real_path="$(readlink -f "$dir/BESTPRACTICES.md")"
    if [[ -z "${emitted_files[$real_path]:-}" ]]; then
        emit_file "$dir/BESTPRACTICES.md"
        emitted_files["$real_path"]=1
    fi
done

# --- Output: all *.md files in cwd ---

if compgen -G "$PWD"/*.md > /dev/null 2>&1; then
    for md_file in "$PWD"/*.md; do
        [[ -f "$md_file" ]] || continue
        real_path="$(readlink -f "$md_file")"
        if [[ -z "${emitted_files[$real_path]:-}" ]]; then
            emit_file "$md_file"
            emitted_files["$real_path"]=1
        fi
    done
fi

# --- Output: git status report ---

if [[ ${#claude_dirs[@]} -gt 0 ]]; then
    highest_dir="${claude_dirs[0]}"
    git_status_report="$(command -v git-status-report 2>/dev/null || true)"
    if [[ -n "$git_status_report" ]]; then
        emit_header "GIT STATUS: $highest_dir"
        "$git_status_report" "$highest_dir" 2>/dev/null | strip_ansi || true
    fi
fi
