#!/usr/bin/env bash
# deployment-node.sh - To be run on the execution node (SOLARIA, PIHA, VPS)
# This script pulls the latest changes and ensures services are running.

set -e

# Configuration
REPO_PATH="${HOME}/homelab-codex-ws"
# Env-overridable so the script can be exercised against a scratch runtime dir
# without writing into the node's real /opt/homelab.
RUNTIME_PATH="${RUNTIME_PATH:-/opt/homelab}"
HOSTNAME=$(hostname | tr '[:lower:]' '[:upper:]')
CURRENT_OS_HOST=$(hostname)

echo "--- Starting Deployment on ${HOSTNAME} ---"

# 1. Update Repository
if [ ! -d "$REPO_PATH" ]; then
    echo "Error: Repository not found at $REPO_PATH"
    exit 1
fi

cd "$REPO_PATH"
echo "Pulling latest changes..."
git pull

# Resolve host directory: search hosts/*/host.yaml for os_hostname == $(hostname)
HOST_LOGICAL=$(python3 -c "
import yaml, os, sys
current = '${CURRENT_OS_HOST}'
hosts_dir = os.path.join('${REPO_PATH}', 'hosts')
for entry in sorted(os.listdir(hosts_dir)):
    host_yaml = os.path.join(hosts_dir, entry, 'host.yaml')
    if not os.path.isfile(host_yaml):
        continue
    try:
        with open(host_yaml) as f:
            data = yaml.safe_load(f)
        if data and data.get('os_hostname') == current:
            print(entry)
            sys.exit(0)
    except Exception:
        pass
")

if [ -n "$HOST_LOGICAL" ]; then
    HOST_DIR="${REPO_PATH}/hosts/${HOST_LOGICAL}"
else
    HOST_LOGICAL_FB="$(echo "$CURRENT_OS_HOST" | tr '[:upper:]' '[:lower:]')"
    echo "WARN: no os_hostname match for ${CURRENT_OS_HOST}, falling back to lowercase hostname dir" >&2
    HOST_DIR="${REPO_PATH}/hosts/${HOST_LOGICAL_FB}"
fi

if [ ! -d "$HOST_DIR" ]; then
    echo "Error: No host directory found for ${CURRENT_OS_HOST} (tried ${HOST_DIR})" >&2
    exit 1
fi

# 2. Identify Services
SERVICES=()
if [ -f "${HOST_DIR}/services.txt" ]; then
    mapfile -t SERVICES < <(grep -v '^\s*#' "${HOST_DIR}/services.txt" | grep -v '^\s*$')
elif [ -f "${HOST_DIR}/services.yaml" ]; then
    SERVICES=($(python3 -c "
import yaml, sys
try:
    with open('${HOST_DIR}/services.yaml', 'r') as f:
        data = yaml.safe_load(f)
        if data and 'services' in data:
            if isinstance(data['services'], dict):
                print(' '.join(data['services'].keys()))
            elif isinstance(data['services'], list):
                print(' '.join(data['services']))
except Exception as e:
    print(f'Error parsing YAML: {e}', file=sys.stderr)
    sys.exit(1)
"))
fi

if [ ${#SERVICES[@]} -eq 0 ]; then
    echo "No services found for ${HOSTNAME}. Skipping service deployment."
    exit 0
fi

# 3. Deploy Services
#
# The per-service compose invocation lives in deploy-service.sh, shared with the
# agent-driven single-service redeploy (services/deploy-runner/). Both callers
# MUST assemble the -f arguments identically: docker compose derives the project
# name from the first -f file's directory, and a mismatch plus --remove-orphans
# is what wiped the control-plane on VPS on 2026-06-25. Services with their own
# deploy-local.sh are skipped by deploy-service.sh (exit 3).
DEPLOY_SERVICE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/deploy-service.sh"

for service in "${SERVICES[@]}"; do
    TARGET_DIR="${RUNTIME_PATH}/services/${service}"
    mkdir -p "$TARGET_DIR"

    rc=0
    "$DEPLOY_SERVICE" \
        --repo "$REPO_PATH" \
        --host-dir "$HOST_DIR" \
        --service "$service" \
        --build-if-needed \
        --remove-orphans || rc=$?

    case "$rc" in
        0) ;;                       # deployed
        3) ;;                       # owns its deploy path — already reported, skip
        2) echo "Warning: skipping ${service} (validation failed, see above)" ;;
        *) exit "$rc" ;;            # real deploy failure — preserve set -e semantics
    esac
done

echo "--- Deployment Complete ---"
