# agent-config.sh — GPU group membership, agent config overlay, and AGENTS.md merge.
# shellcheck shell=bash
# Requires: warn (from helpers.sh).
# Called in a subshell (Group B) for parallelism — no side effects on parent state.
# Copyright (c) 2026 Progralink. Licensed under the DevCage License — see LICENSE.

# _setup_agent_config: GPU groups, per-agent config overlay, git config, AGENTS.md merge.
_setup_agent_config() {
    # ── GPU device group membership ───────────────────────────────
    # If GPU devices are present (NVIDIA or AMD), add devcage to the
    # video and render groups so the unprivileged user can access them.
    if [ -e /dev/nvidia0 ] || [ -e /dev/nvidiactl ] || [ -e /dev/kfd ] || [ -d /dev/dri ]; then
        local _grp
        for _grp in video render; do
            if getent group "$_grp" >/dev/null 2>&1; then
                usermod -aG "$_grp" devcage 2>/dev/null || warn "failed to add devcage to ${_grp} group"
            fi
        done
    fi

    # ── Agent configuration overlay ───────────────────────────────
    # Controlled by AGENT_CONFIG_RO:
    #   1 (default) – host config dirs mounted read-only under /agent-config/,
    #                 overlaid into container home; host is untouched.
    #   0           – host config dirs mounted directly at home paths;
    #                 settings changes persist back to host.
    #   skip        – skip agent config overlay entirely (no host configs mounted).
    local _CONFIG_RO="${AGENT_CONFIG_RO:-1}"

    if [ "$_CONFIG_RO" = "skip" ]; then
        : # --host-agents-config no/disabled: skip all agent config handling
    elif [ "$_CONFIG_RO" = "1" ]; then
        # ── Agent state persistence (directory-based agents) ──────────
        # Each agent's home dir is symlinked into the workspace so ALL
        # state (conversations, sessions, history, memory, plans, etc.)
        # survives container restarts.  Host config is re-overlaid on top
        # each startup so credentials and settings stay fresh.
        #   agent-config key : home path
        local _agent_persist_map=(
            "claude:/home/devcage/.claude"
            "gemini-cli:/home/devcage/.config/gemini-cli"
            "codex:/home/devcage/.codex"
            "copilot:/home/devcage/.copilot"
            "goose:/home/devcage/.config/goose"
        )
        # Ensure the agents parent dir exists and is git-ignored
        install -d -o devcage -g devcage /workspace/.devcage/agents
        if [ ! -f /workspace/.devcage/agents/.gitignore ]; then
            printf '*\n' > /workspace/.devcage/agents/.gitignore
            chown devcage:devcage /workspace/.devcage/agents/.gitignore
        fi

        local _ap_entry _ap_key _ap_home _ap_state
        for _ap_entry in "${_agent_persist_map[@]}"; do
            _ap_key="${_ap_entry%%:*}"
            _ap_home="${_ap_entry##*:}"
            [ -d "/agent-config/${_ap_key}" ] || continue

            _ap_state="/workspace/.devcage/agents/${_ap_key}"
            install -d -o devcage -g devcage "$_ap_state"

            # Fast-path: skip symlink recreation if already pointing to correct target
            if [ -L "$_ap_home" ] && [ "$(readlink "$_ap_home")" = "$_ap_state" ]; then
                : # symlink already correct
            else
                # Remove stale symlink or ephemeral dir from previous overlay
                if [ -L "$_ap_home" ]; then
                    rm -f "$_ap_home"
                elif [ -d "$_ap_home" ]; then
                    rm -rf "$_ap_home"
                fi

                # Symlink home dir → workspace-persisted dir
                mkdir -p "$(dirname "$_ap_home")"
                ln -sf "$_ap_state" "$_ap_home"
            fi

            # Overlay host config on top (refreshes credentials/settings
            # each restart while preserving accumulated state)
            cp -rL --preserve=mode,timestamps "/agent-config/${_ap_key}/." "$_ap_state/" 2>/dev/null || true

            chown -Rh devcage:devcage "$_ap_state" 2>/dev/null || true
        done

        # ── Single-file agent configs (not directory-based) ───────────
        # Claude: macOS Keychain credential (mounted separately)
        # Written to /run/devcage/ (tmpfs, not workspace-persisted) so it doesn't
        # leak into /workspace/.devcage/agents/claude/ via the symlink.
        if [ -f /agent-config/claude-credentials.json ]; then
            install -d -o devcage -g devcage -m 700 /run/devcage
            cp /agent-config/claude-credentials.json /run/devcage/.credentials.json
            chown devcage:devcage /run/devcage/.credentials.json
            chmod 600 /run/devcage/.credentials.json
            # Claude Code reads from ~/.claude/.credentials.json — create a
            # symlink from the persisted dir to the tmpfs copy.
            local _claude_state="/workspace/.devcage/agents/claude"
            if [ -d "$_claude_state" ]; then
                ln -sf /run/devcage/.credentials.json "$_claude_state/.credentials.json"
                chown -h devcage:devcage "$_claude_state/.credentials.json"
            fi
        fi
        # Claude: ~/.claude.json (onboarding state, theme)
        if [ -f /agent-config/claude.json ]; then
            cp /agent-config/claude.json /home/devcage/.claude.json
            chown devcage:devcage /home/devcage/.claude.json
        fi
        # Aider: single config file (state lives in CWD, persists naturally)
        if [ -f /agent-config/aider.conf.yml ]; then
            cp /agent-config/aider.conf.yml /home/devcage/.aider.conf.yml
            chown devcage:devcage /home/devcage/.aider.conf.yml
        fi
    fi

    # ── Git config overlay (--git-auth) ──────────────────────────────
    # Suppress verbose tracing around credential handling to avoid leaking secrets
    local _verbose_was_on=0
    { case $- in *x*) _verbose_was_on=1; set +x ;; esac; } 2>/dev/null
    if [ -f /agent-config/gitconfig ]; then
        cp /agent-config/gitconfig /home/devcage/.gitconfig
        chown devcage:devcage /home/devcage/.gitconfig
    fi
    if [ -f /agent-config/git-credentials ]; then
        # Store on tmpfs (like Claude OAuth) so credentials don't persist in overlayfs
        install -d -o devcage -g devcage -m 700 /run/devcage 2>/dev/null || true
        cp /agent-config/git-credentials /run/devcage/.git-credentials
        chown devcage:devcage /run/devcage/.git-credentials
        chmod 600 /run/devcage/.git-credentials
        ln -sf /run/devcage/.git-credentials /home/devcage/.git-credentials
        chown -h devcage:devcage /home/devcage/.git-credentials
        # Enable credential-store if not already configured in .gitconfig
        if ! grep -q 'credential.helper' /home/devcage/.gitconfig 2>/dev/null; then
            su devcage -c 'git config --global credential.helper store'
        fi
    fi
    if [ "$_verbose_was_on" = "1" ]; then set -x; fi

    # Ensure sandbox instructions exist at each tool's expected path.
    # Symlinks point to the canonical SANDBOX_AGENTS.md.
    # If the host config overlay provided a real file, it takes precedence
    # (cp -rL dereferences symlinks during overlay, replacing them with real files from host).
    local _SANDBOX_MD="/home/devcage/SANDBOX_AGENTS.md"
    local _link
    for _link in /home/devcage/CLAUDE.md /home/devcage/.gemini/GEMINI.md /home/devcage/.codex/AGENTS.md; do
        if [ ! -e "$_link" ]; then
            mkdir -p "$(dirname "$_link")"
            ln -sf "$_SANDBOX_MD" "$_link"
        fi
    done
    chown -h devcage:devcage /home/devcage/CLAUDE.md /home/devcage/.gemini/GEMINI.md /home/devcage/.codex/AGENTS.md 2>/dev/null || true

    # ── Merge AGENTS.md files from /sandbox-agents.d/ ─────────────────
    # Additional agent instructions are appended to the base SANDBOX_AGENTS.md
    # with clear separators. No confirmation needed (instructions, not executable).
    # Save original on first run so container restarts don't accumulate duplicates.
    if [ ! -f "${_SANDBOX_MD}.orig" ]; then
        cp "$_SANDBOX_MD" "${_SANDBOX_MD}.orig"
    fi
    cp "${_SANDBOX_MD}.orig" "$_SANDBOX_MD"
    if [ -d /sandbox-agents.d ]; then
        local _agents_count=0 _agentf
        for _agentf in /sandbox-agents.d/*.md; do
            [ -f "$_agentf" ] || continue
            _agents_count=$(( _agents_count + 1 ))
            # Append with a clear separator (2 blank lines + --- + 2 blank lines)
            # Use sed to strip CRLF during copy (files may be read-only mounted)
            printf '\n\n---\n\n' >> "$_SANDBOX_MD"
            sed 's/\r$//' "$_agentf" >> "$_SANDBOX_MD"
        done
        if [ "$_agents_count" -gt 0 ]; then
            echo "entrypoint: merged ${_agents_count} AGENTS.md file(s) into sandbox instructions" >&2
            chown devcage:devcage "$_SANDBOX_MD"
        fi
    fi

    # Goose reads .goosehints from workspace root (not config directory)
    if [ ! -e /workspace/.goosehints ]; then
        ln -sf "$_SANDBOX_MD" /workspace/.goosehints
        chown -h devcage:devcage /workspace/.goosehints 2>/dev/null || true
    fi
}
