#!/usr/bin/env bash
# Copyright (c) 2026 Progralink. Licensed under the DevCage License — see LICENSE.
#
# entrypoint.sh — Orchestrator. Sources modules from /usr/local/lib/devcage/.
# All implementation lives in the modules; this file manages ordering and concurrency.
set -euo pipefail

_LIB="/usr/local/lib/devcage"
for _m in helpers verbose uid-remap cache-setup agent-config network \
           packages toolset-cleanup approval init-scripts crontab \
           reuse-mode exec-drop; do
    # shellcheck source=/dev/null
    . "${_LIB}/${_m}.sh"
done

# ── Verbose mode (set -x + API key masking) ─────────────────────
_setup_verbose
[ $# -eq 0 ] && echo "" >&2

# ── Log init start ──────────────────────────────────────────────
_entrypoint_log "=== Entrypoint Init ==="
_entrypoint_log "Date: $(date '+%Y-%m-%d %H:%M:%S %Z')"
_entrypoint_log "HOST_UID=${HOST_UID:-unset}"

# ── UID remapping + workspace ownership ─────────────────────────
_remap_uid
_fix_workspace_ownership

# Persistent project context lives inside the workspace mount so it
# survives container restarts without a separate Docker volume.
install -d -o devcage -g devcage /workspace/.devcage/context

# Ensure optional infrastructure directories exist so tools and tests
# always find them, even when no config files are mounted.
[ -d /sandbox-crontab.d ] || mkdir -p /sandbox-crontab.d
[ -d /sandbox-agents.d ]  || mkdir -p /sandbox-agents.d

# ── Parallel init: A (cache) + B (agent config) in background ───
# ── while C (iptables) runs in foreground. A, B, C independent. ─
( set -euo pipefail; _setup_cache ) &        _pid_a=$!
( set -euo pipefail; _setup_agent_config ) & _pid_b=$!
_setup_network_isolation                     # foreground (fills wait time)

_bg_fail=0
wait "$_pid_a" 2>/dev/null || { warn "cache setup failed (Group A)"; _bg_fail=1; }
wait "$_pid_b" 2>/dev/null || { warn "agent config failed (Group B)"; _bg_fail=1; }
[ "$_bg_fail" = "0" ] || die "background init failed — see warnings above"

# ── Best-effort kernel hardening ────────────────────────────────
# Docker mounts /proc/sys read-only by default — these typically fail.
# The real defense-in-depth comes from zero capabilities.
{ echo 2 > /proc/sys/kernel/kptr_restrict; } 2>/dev/null || true
{ echo 1 > /proc/sys/kernel/dmesg_restrict; } 2>/dev/null || true

# ── Sequential init (shared _validated_pkgs — must not parallelize) ─
_install_apt_packages
_install_brew_packages
_install_snap_packages
_cleanup_disabled_toolsets

# Privilege drop args — verify setpriv is available before going further
_setup_setpriv_args
export HOME=/home/devcage USER=devcage

_setup_sdkman
_process_init_scripts
_build_cmd_preamble
_process_crontab

_start_wsl2_keepalive

_entrypoint_log "Initialization complete"

# Signal successful initialization for health-check
touch /tmp/.devcage-ready

# Restore masked API keys before handing off to the agent process.
# Must run AFTER touch /tmp/.devcage-ready, BEFORE exec.
_restore_secrets

# Disable set -e so die() is reachable if exec fails (a failed exec returns
# but set -e would exit the shell before the || branch runs).
set +e

if [ "${DEVCAGE_REUSE:-0}" = "1" ]; then _enter_reuse_mode; fi
_exec_single_shot "$@"
