#!/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:
#   - Paths to every CLAUDE.md found walking up from cwd (not contents — Claude Code loads those natively)
#   - Paths to every project CLAUDE.md found under each CLAUDE.md directory (for project discovery)
#   - 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)
set -uo pipefail

# --- Helpers ---

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

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

# Extract description from ABOUT.md in the same directory as a CLAUDE.md
get_project_description() {
    local claude_path="$1"
    local dir
    dir="$(dirname "$claude_path")"
    local about="$dir/ABOUT.md"
    if [[ -f "$about" ]]; then
        sed -n 's/^description:[[:space:]]*//p' "$about" | head -1
    fi
}

# --- 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=()

while IFS= read -r dir; do
    [[ -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 paths (not contents — Claude Code loads those natively) ---
# Also discover project CLAUDE.md files under each directory for project listing

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

emit_header "CLAUDE.md FILES"
for dir in "${claude_dirs[@]}"; do
    real_path="$(readlink -f "$dir/CLAUDE.md")"
    if [[ -z "${emitted_files[$real_path]:-}" ]]; then
        desc="$(get_project_description "$dir/CLAUDE.md")"
        if [[ -n "$desc" ]]; then
            echo "- $dir/CLAUDE.md — $desc"
        else
            echo "- $dir/CLAUDE.md"
        fi
        emitted_files["$real_path"]=1
    fi
done

# Discover project CLAUDE.md files (depth 2-4 under each CLAUDE.md dir)
# This replaces the old tree output — gives Claude a fresh project listing
project_claudes=()
for dir in "${claude_dirs[@]}"; do
    while IFS= read -r f; do
        real_path="$(readlink -f "$f")"
        if [[ -z "${emitted_files[$real_path]:-}" ]]; then
            project_claudes+=("$f")
            emitted_files["$real_path"]=1
        fi
    done < <(find "$dir" -mindepth 2 -maxdepth 4 -name CLAUDE.md -not -path '*/.git/*' -not -path '*/node_modules/*' -not -path '*/__pycache__/*' 2>/dev/null | sort)
done

if [[ ${#project_claudes[@]} -gt 0 ]]; then
    echo ""
    echo "Project CLAUDE.md files:"
    for f in "${project_claudes[@]}"; do
        desc="$(get_project_description "$f")"
        if [[ -n "$desc" ]]; then
            echo "- $f — $desc"
        else
            echo "- $f"
        fi
    done
fi
echo ""

# --- 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
