#!/bin/bash
# TODO: Add `set -u` to catch undefined variable usage early
# ============================================
# SPECMEM BRAIN CONTAINER ENTRYPOINT
# ============================================
# 1. Initialize pgdata if not exists
# 2. Start PostgreSQL, create DB + pgvector extension
# 3. Start supervisord (all services)
# 4. Health check loop → /data/run/health.json
# ============================================

set -e

DATA_DIR="${SPECMEM_CONTAINER_DATA:-/data}"
PGDATA="${DATA_DIR}/pgdata"
RUN_DIR="${DATA_DIR}/run"
LOG_DIR="${DATA_DIR}/logs"

# Ensure directories exist
mkdir -p "$RUN_DIR" "$LOG_DIR" "${DATA_DIR}/exports"

echo "[entrypoint] SpecMem Brain starting..." >&2

# Handle running as root (rootless podman UID remapping)
# If we're root, create specmem user if missing, fix perms, and re-exec as specmem
if [ "$(id -u)" = "0" ]; then
    echo "[entrypoint] Running as root — creating specmem user and dropping privileges" >&2
    id specmem &>/dev/null 2>&1 || useradd -r -m -s /bin/bash specmem 2>/dev/null || true
    # IMPORTANT: Only chown brain-specific subdirs, NOT the entire /data tree!
    # /data may contain host source files (npm package) that should keep their ownership
    mkdir -p "$RUN_DIR" "$LOG_DIR" "${DATA_DIR}/pgdata" "${DATA_DIR}/exports"
    chown -R specmem:specmem "$RUN_DIR" "$LOG_DIR" "${DATA_DIR}/pgdata" "${DATA_DIR}/exports" /app 2>/dev/null || true
    chmod 777 "$RUN_DIR" "$LOG_DIR" "${DATA_DIR}/exports" 2>/dev/null || true
    # Set umask so sockets/files are world-accessible (host user needs to connect)
    umask 000
    # Re-exec this script as specmem user
    exec runuser -u specmem -- "$0" "$@"
else
    echo "[entrypoint] Running as non-root (uid=$(id -u)) — ensuring dirs are writable" >&2
    # Docker with USER specmem: host should have set dirs to 777, but verify
    # IMPORTANT: pgdata needs 700, NOT 777 (PostgreSQL security requirement)
    for d in "$RUN_DIR" "$LOG_DIR" "${DATA_DIR}/exports"; do
        mkdir -p "$d" 2>/dev/null || true
        chmod 777 "$d" 2>/dev/null || true
    done
    # pgdata: must be 700 or 750 for PostgreSQL
    if [ -d "${DATA_DIR}/pgdata" ]; then
        chmod 700 "${DATA_DIR}/pgdata" 2>/dev/null || true
    fi
fi

# Ensure world-accessible sockets for host processes
umask 000

# ============================================
# PostgreSQL initialization
# ============================================
if [ ! -f "${PGDATA}/PG_VERSION" ]; then
    echo "[entrypoint] Initializing PostgreSQL data directory..." >&2

    # TODO: Cache initdb/pg_ctl/psql paths at script start instead of finding on each use
    # Find initdb binary
    INITDB=$(find /usr/lib/postgresql -name initdb -type f 2>/dev/null | head -1)
    if [ -z "$INITDB" ]; then
        echo "[entrypoint] FATAL: initdb not found" >&2
        exit 1
    fi

    # Initialize with trust auth (container-internal only, no network)
    "$INITDB" \
        --pgdata="$PGDATA" \
        --username=specmem \
        --auth=trust \
        --no-locale \
        --encoding=UTF8 \
        2>&1 | tee "${LOG_DIR}/initdb.log" >&2

    # Configure for unix socket only — NO TCP
    cat >> "${PGDATA}/postgresql.conf" <<PGEOF
# SpecMem container config — localhost TCP + unix sockets
# TCP needed so host init can connect to pg via the bind-mounted port
listen_addresses = 'localhost'
unix_socket_directories = '${RUN_DIR}'
port = 5432

# Performance tuning for container
shared_buffers = 256MB
work_mem = 16MB
maintenance_work_mem = 128MB
effective_cache_size = 512MB
max_connections = 100

# WAL settings
wal_level = minimal
max_wal_senders = 0
fsync = on
synchronous_commit = off

# Logging
log_destination = 'stderr'
logging_collector = off
log_min_messages = warning
PGEOF

    # Allow local connections only (trust — container is air-gapped)
    cat > "${PGDATA}/pg_hba.conf" <<HBAEOF
# TYPE  DATABASE  USER  ADDRESS  METHOD
local   all       all            trust
HBAEOF

    echo "[entrypoint] PostgreSQL initialized" >&2
fi

# ============================================
# Start PostgreSQL
# ============================================
PG_CTL=$(find /usr/lib/postgresql -name pg_ctl -type f 2>/dev/null | head -1)
if [ -z "$PG_CTL" ]; then
    echo "[entrypoint] FATAL: pg_ctl not found" >&2
    exit 1
fi

# ============================================
# Auto-fix: Clean stale locks and fix permissions
# ============================================
echo "[entrypoint] Checking for stale locks and permissions..." >&2

# 1. Remove stale postmaster.pid (prevents "another server might be running")
if [ -f "${PGDATA}/postmaster.pid" ]; then
    echo "[entrypoint] Removing stale postmaster.pid" >&2
    rm -f "${PGDATA}/postmaster.pid"
fi

# 2. Remove stale PostgreSQL sockets
rm -f "${RUN_DIR}/.s.PGSQL."* 2>/dev/null || true

# 3. Fix pgdata permissions (PostgreSQL requires 0700 or 0750, rejects 0777)
if [ -d "$PGDATA" ]; then
    current_perms=$(stat -c '%a' "$PGDATA" 2>/dev/null || echo "unknown")
    if [ "$current_perms" != "700" ] && [ "$current_perms" != "750" ]; then
        echo "[entrypoint] Fixing pgdata permissions: $current_perms → 700" >&2
        chmod 700 "$PGDATA" 2>/dev/null || {
            echo "[entrypoint] WARNING: Could not chmod pgdata (continuing anyway)" >&2
        }
    fi
fi

# 4. Fix RUN_DIR permissions for bind mounts (anyone must access sockets)
if [ -d "$RUN_DIR" ]; then
    echo "[entrypoint] Fixing run directory permissions for bind mounts..." >&2
    # Ensure sockets directory is accessible
    chmod 777 "$RUN_DIR" 2>/dev/null || true
    # Fix any stale socket files
    rm -f "${RUN_DIR}"/*.sock 2>/dev/null || true
fi

# 5. Fix status file permissions
if [ -f "$RUN_DIR/embedding-status.json" ]; then
    chmod 666 "$RUN_DIR/embedding-status.json" 2>/dev/null || true
fi
if [ -f "$RUN_DIR/health.json" ]; then
    chmod 666 "$RUN_DIR/health.json" 2>/dev/null || true
fi

echo "[entrypoint] Starting PostgreSQL..." >&2
"$PG_CTL" start \
    -D "$PGDATA" \
    -l "${LOG_DIR}/postgresql.log" \
    -o "-k ${RUN_DIR}" \
    -w -t 30

# Wait for socket to appear
for i in $(seq 1 30); do
    if [ -S "${RUN_DIR}/.s.PGSQL.5432" ]; then
        echo "[entrypoint] PostgreSQL socket ready" >&2
        break
    fi
    sleep 0.5
done

if [ ! -S "${RUN_DIR}/.s.PGSQL.5432" ]; then
    echo "[entrypoint] FATAL: PostgreSQL socket not found after 15s" >&2
    cat "${LOG_DIR}/postgresql.log" >&2
    exit 1
fi

# ============================================
# Create database + pgvector extension
# ============================================
PSQL=$(find /usr/lib/postgresql -name psql -type f 2>/dev/null | head -1)
if [ -z "$PSQL" ]; then
    PSQL="psql"
fi

# Create specmem database if not exists
"$PSQL" -h "$RUN_DIR" -U specmem -d postgres -tc \
    "SELECT 1 FROM pg_database WHERE datname = 'specmem'" \
    | grep -q 1 || \
    "$PSQL" -h "$RUN_DIR" -U specmem -d postgres -c "CREATE DATABASE specmem"

# Enable pgvector
"$PSQL" -h "$RUN_DIR" -U specmem -d specmem -c "CREATE EXTENSION IF NOT EXISTS vector" 2>/dev/null || \
    echo "[entrypoint] WARNING: pgvector extension not available" >&2

echo "[entrypoint] Database ready" >&2

# ============================================
# Auto-detect project schema (created by host MCP)
# ============================================
# The host MCP creates tables in a schema like specmem_<project_dir>
# Python services need this schema name to find tables
DETECTED_SCHEMA=$("$PSQL" -h "$RUN_DIR" -U specmem -d specmem -Atc \
    "SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE 'specmem_%' ORDER BY schema_name LIMIT 1" \
    2>/dev/null || echo "")
if [ -n "$DETECTED_SCHEMA" ]; then
    echo "[entrypoint] Detected project schema: $DETECTED_SCHEMA" >&2
    export SPECMEM_DB_SCHEMA="$DETECTED_SCHEMA"
    # Write to file so supervisord child processes can read it
    echo "$DETECTED_SCHEMA" > "${RUN_DIR}/project-schema"
else
    echo "[entrypoint] No project schema found yet (will be created by host MCP)" >&2
fi

# ============================================
# Stop PostgreSQL (supervisord will manage it)
# ============================================
"$PG_CTL" stop -D "$PGDATA" -m fast -w -t 10
echo "[entrypoint] PostgreSQL stopped (supervisord will restart)" >&2

# ============================================
# Write initial health status
# ============================================
cat > "${RUN_DIR}/health.json" <<HEALTHEOF
{
  "status": "starting",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "postgres": "starting",
  "embedding": "starting",
  "translate": "starting"
}
HEALTHEOF

# ============================================
# Start supervisord (manages all services)
# ============================================
echo "[entrypoint] Starting supervisord..." >&2
exec /usr/bin/supervisord -n -c /etc/supervisor/conf.d/specmem.conf
