#!/usr/bin/env bash
# uvlava — infranet Task Runner
# Usage: ./run <command> [args...]
#
# Manages the services under services/ (each a dir with deploy.sh + compose.yml,
# deployed to /opt/<service> on its target droplet) and wraps the DO terraform.
#
#   ./run services                 List discovered services + their targets.
#   ./run deploy <svc> [user@host]  Run services/<svc>/deploy.sh (build+ship+wire).
#   ./run status <svc> [target]    docker compose ps (+ health probe if defined).
#   ./run logs   <svc> [target] [-- <compose logs args>]
#   ./run restart <svc> [target]   docker compose restart on the droplet.
#   ./run tf <args...>             terraform in terraform/do/ (token from vault).
#
# A service's target host resolves from services/<svc>/.target (one line,
# user@host) else DEFAULT_TARGET. Health probe: services/<svc>/.health (one line,
# a URL curl'd on the droplet, e.g. http://127.0.0.1:8090/healthz).
#
# Follows the ./run task-runner convention (cf. @applications/prospector/run).

set -uo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SERVICES_DIR="$REPO_ROOT/services"
DEFAULT_TARGET="root@134.199.243.61"   # com.uvlava.quinn.artifacts (forge droplet)

RED=$'\e[31m' YELLOW=$'\e[33m' BLUE=$'\e[34m' GREEN=$'\e[32m' NC=$'\e[0m' || true

die() { echo -e "${RED}uvlava: $*${NC}" >&2; exit 1; }

# Fleet SSH. Cloud droplets get rebuilt (IP reused, host key changes), so we keep
# a DEDICATED known_hosts for the fleet (never conflicts with the user's main
# file), TOFU-accept new keys, and self-heal a changed key (rebuilt host) by
# dropping the stale entry and retrying once. Uses the fleet key when present.
FLEET_KH="$HOME/.ssh/known_hosts_uvlava"
SSH="ssh -o StrictHostKeyChecking=accept-new -o CheckHostIP=no -o UserKnownHostsFile=$FLEET_KH"
[ -f "$HOME/.ssh/id_ed25519_1984" ] && SSH="$SSH -i $HOME/.ssh/id_ed25519_1984"

fssh() {  # fssh user@host "remote command..."
    local target="$1"; shift
    local host="${target#*@}" err
    err="$(mktemp)"
    if $SSH "$target" "$@" 2>"$err"; then rm -f "$err"; return 0; fi
    if grep -qiE "host key.*changed|REMOTE HOST IDENTIFICATION HAS CHANGED" "$err"; then
        ssh-keygen -R "$host" -f "$FLEET_KH" >/dev/null 2>&1 || true
        rm -f "$err"; $SSH "$target" "$@"; return $?
    fi
    cat "$err" >&2; rm -f "$err"; return 1
}

# A service = a dir under services/ that has a deploy.sh.
list_services() {
    [ -d "$SERVICES_DIR" ] || return 0
    for d in "$SERVICES_DIR"/*/; do
        [ -f "${d}deploy.sh" ] && basename "$d"
    done
}
require_service() {
    local svc="$1"
    [ -n "$svc" ] || die "missing <service> (see: ./run services)"
    [ -f "$SERVICES_DIR/$svc/deploy.sh" ] || die "unknown service '$svc' (see: ./run services)"
}
service_target() {  # resolves a service's deploy target
    local svc="$1" f="$SERVICES_DIR/$1/.target"
    [ -f "$f" ] && head -1 "$f" || echo "$DEFAULT_TARGET"
}

usage() {
    echo -e "${BLUE}uvlava${NC} — infranet Task Runner"
    echo ""
    echo "Usage: ./run <command> [args...]"
    echo ""
    echo -e "${YELLOW}Services (services/<name>/)${NC}"
    echo "  services                 List services + resolved targets."
    echo "  deploy <svc> [target]    Build + ship + wire (delegates to its deploy.sh)."
    echo "  status <svc> [target]    docker compose ps (+ health probe if defined)."
    echo "  logs   <svc> [target]    docker compose logs (pass extra args after --)."
    echo "  restart <svc> [target]   docker compose restart on the droplet."
    echo ""
    echo -e "${YELLOW}Infrastructure${NC}"
    echo "  tf <args...>             terraform in terraform/do/ (do_token from ~/.vault)."
    echo ""
    if [ -n "$(list_services)" ]; then
        echo -e "${YELLOW}Discovered services${NC}"
        while read -r s; do printf '  %-16s -> %s\n' "$s" "$(service_target "$s")"; done < <(list_services)
    fi
}

cmd_services() {
    local any=0
    while read -r s; do any=1; printf '%-16s -> %s\n' "$s" "$(service_target "$s")"; done < <(list_services)
    [ "$any" = 1 ] || echo "(no services under $SERVICES_DIR — a service is a dir with deploy.sh)"
}

cmd_deploy() {
    local svc="${1:-}"; require_service "$svc"; shift
    echo -e "${GREEN}==> deploy $svc${NC}"
    exec "$SERVICES_DIR/$svc/deploy.sh" "$@"
}

cmd_status() {
    local svc="${1:-}"; require_service "$svc"
    local target="${2:-$(service_target "$svc")}"
    echo -e "${GREEN}==> $svc @ $target${NC}"
    fssh "$target" "cd /opt/$svc && docker compose ps" || die "compose ps failed on $target"
    local health="$SERVICES_DIR/$svc/.health"
    if [ -f "$health" ]; then
        local url; url="$(head -1 "$health")"
        echo "--- health: $url ---"
        fssh "$target" "curl -fsS '$url'" && echo || echo -e "${RED}(health probe failed)${NC}"
    fi
}

cmd_logs() {
    local svc="${1:-}"; require_service "$svc"
    local target="${2:-$(service_target "$svc")}"; shift 2>/dev/null || true; shift 2>/dev/null || true
    # everything after `--` is forwarded to `docker compose logs`
    [ "${1:-}" = "--" ] && shift
    local extra="${*:---tail=100}"
    fssh "$target" "cd /opt/$svc && docker compose logs $extra"
}

cmd_restart() {
    local svc="${1:-}"; require_service "$svc"
    local target="${2:-$(service_target "$svc")}"
    echo -e "${GREEN}==> restart $svc @ $target${NC}"
    fssh "$target" "cd /opt/$svc && docker compose restart"
}

cmd_tf() {
    local tfdir="$REPO_ROOT/terraform/do"
    [ -d "$tfdir" ] || die "no terraform dir at $tfdir"
    local tok=""
    for c in "$HOME/.vault/do-pat-ct.token" "$HOME/.vault/do_pat_ct" "$HOME/.vault/do_pat_cocotte"; do
        [ -f "$c" ] && { tok="$(cat "$c")"; break; }
    done
    [ -n "$tok" ] || die "no DO token found in ~/.vault (do-pat-ct.token / do_pat_cocotte)"
    (cd "$tfdir" && TF_VAR_do_token="$tok" terraform "$@")
}

COMMAND="${1:-}"; shift 2>/dev/null || true
case "$COMMAND" in
    help|--help|-h|"") usage; exit 0 ;;
    services|ls)       cmd_services "$@" ;;
    deploy)            cmd_deploy "$@" ;;
    status)            cmd_status "$@" ;;
    logs)              cmd_logs "$@" ;;
    restart)           cmd_restart "$@" ;;
    tf|terraform)      cmd_tf "$@" ;;
    *) echo -e "${RED}Unknown command: $COMMAND${NC}" >&2; usage; exit 1 ;;
esac
