#!/usr/bin/env bash
set -euo pipefail

SERVICE="gal2-node.service"
CONTAINER="gal2-node"
BASE_URL="${GAL2_NODE_URL:-http://127.0.0.1:9095}"
SHM_PATH="${GAL2_SHM_PATH:-/run/gal2/contract-v1.shm}"

run_as_root() {
  if [ "${EUID}" -eq 0 ]; then
    "$@"
  elif command -v sudo >/dev/null 2>&1; then
    sudo "$@"
  else
    echo "ERROR: root privileges are required for this operation." >&2
    return 1
  fi
}

get_json() {
  local path="$1"

  curl \
    --fail \
    --silent \
    --show-error \
    --max-time 5 \
    "${BASE_URL}/${path}"

  echo
}

show_container() {
  local docker_output=""

  if ! command -v docker >/dev/null 2>&1; then
    echo "docker_not_found"
    return 1
  fi

  if docker_output="$(
    docker inspect "$CONTAINER" \
      --format \
      'status={{.State.Status}} running={{.State.Running}} image={{.Config.Image}}' \
      2>&1
  )"
  then
    echo "$docker_output"
    return 0
  fi

  case "$docker_output" in
    *"permission denied"*|*"connect to the docker API"*)
      echo "docker_inspect_permission_denied"
      ;;
    *)
      echo "container_not_found"
      ;;
  esac

  return 1
}

probe_shm() {
  run_as_root docker exec -i "$CONTAINER" python - <<'PYTHON'
from __future__ import annotations

import json
import os
import stat
import sys
import time
import uuid
from pathlib import Path

sys.path.insert(
    0,
    "/opt/gal2/gate2/src",
)

from gal2_shm_v1 import (  # noqa: E402
    FILE_SIZE,
    FLAG_HAS_TIME,
    FLAG_SAFE_TO_CONSUME,
    SLOT_SIZE,
    select_latest_slot,
)


path = Path(
    os.environ.get(
        "GAL2_SHM_PATH",
        "/run/gal2/contract-v1.shm",
    )
)


def read_record() -> dict:
    data = path.read_bytes()

    if len(data) != FILE_SIZE:
        raise RuntimeError(
            "unexpected SHM file size: "
            f"{len(data)}"
        )

    return select_latest_slot(
        [
            data[:SLOT_SIZE],
            data[SLOT_SIZE:],
        ]
    )


first = read_record()
first_sequence = int(
    first["publication_sequence"]
)
first_generation = str(
    first["node_generation_uuid"]
)

uuid.UUID(first_generation)

time.sleep(2.2)

second = read_record()
second_sequence = int(
    second["publication_sequence"]
)
second_generation = str(
    second["node_generation_uuid"]
)

uuid.UUID(second_generation)

file_stat = path.stat()
file_mode = stat.S_IMODE(
    file_stat.st_mode
)

flags = int(second["flags"])

summary = {
    "path": str(path),
    "size_bytes": file_stat.st_size,
    "mode": f"{file_mode:04o}",
    "publication_sequence_initial":
        first_sequence,
    "publication_sequence_current":
        second_sequence,
    "publication_progress":
        second_sequence > first_sequence,
    "generation_initial":
        first_generation,
    "generation_current":
        second_generation,
    "generation_stable":
        first_generation == second_generation,
    "contract_sequence_observed":
        int(
            second[
                "contract_sequence_observed"
            ]
        ),
    "decision": {
        "mode": second["mode"],
        "reason": second["reason"],
        "health": second["health"],
        "safe_to_consume": bool(
            flags & FLAG_SAFE_TO_CONSUME
        ),
        "has_time": bool(
            flags & FLAG_HAS_TIME
        ),
    },
}

print(
    json.dumps(
        summary,
        indent=2,
        sort_keys=True,
    )
)

checks = (
    file_stat.st_size == FILE_SIZE,
    file_mode == 0o644,
    second_sequence > first_sequence,
    first_generation == second_generation,
)

if not all(checks):
    raise SystemExit(1)
PYTHON
}

usage() {
  cat <<'USAGE'
Usage: gal2-node COMMAND

Commands:
  start       Start the GAL-2 Node service
  stop        Stop the GAL-2 Node service
  restart     Restart the GAL-2 Node service
  status      Show service, container, HTTP, and SHM status
  health      Read the local /health endpoint
  contract    Read the local /contract endpoint
  logs        Follow GAL-2 Node service logs
  doctor      Verify lifecycle, HTTP, and SHM publication
  version     Print the package version
USAGE
}

command_name="${1:-}"

case "$command_name" in
  start)
    run_as_root systemctl start "$SERVICE"
    ;;

  stop)
    run_as_root systemctl stop "$SERVICE"
    ;;

  restart)
    run_as_root systemctl restart "$SERVICE"
    ;;

  status)
    echo "=== SYSTEMD ==="

    if command -v systemctl >/dev/null 2>&1; then
      systemctl \
        --no-pager \
        --full \
        status "$SERVICE" ||
        true
    else
      echo "systemctl_not_found"
    fi

    echo
    echo "=== CONTAINER ==="
    show_container || true

    echo
    echo "=== LOCAL HEALTH ==="
    get_json health ||
      echo "health_endpoint_unavailable"

    echo
    echo "=== SHM FILE ==="

    if [ -e "$SHM_PATH" ]; then
      stat \
        --format='path=%n size=%s mode=%a' \
        "$SHM_PATH"
    else
      echo "shm_file_unavailable"
    fi
    ;;

  health)
    get_json health
    ;;

  contract)
    get_json contract
    ;;

  logs)
    run_as_root journalctl -u "$SERVICE" -f
    ;;

  doctor)
    doctor_failed=0

    echo "=== SYSTEMD ==="

    if ! command -v systemctl >/dev/null 2>&1; then
      echo "systemctl_not_found"
      doctor_failed=1
    else
      systemctl is-enabled "$SERVICE" ||
        doctor_failed=1

      systemctl is-active "$SERVICE" ||
        doctor_failed=1
    fi

    echo
    echo "=== CONTAINER ==="

    if ! show_container; then
      doctor_failed=1
    fi

    echo
    echo "=== HEALTH ==="

    if ! get_json health; then
      echo "health_endpoint_unavailable"
      doctor_failed=1
    fi

    echo
    echo "=== CONTRACT ==="

    if ! get_json contract; then
      echo "contract_endpoint_unavailable"
      doctor_failed=1
    fi

    echo
    echo "=== HOST SHM FILE ==="

    if [ ! -e "$SHM_PATH" ]; then
      echo "shm_file_unavailable"
      doctor_failed=1
    else
      shm_size="$(
        stat --format='%s' "$SHM_PATH"
      )"

      shm_mode="$(
        stat --format='%a' "$SHM_PATH"
      )"

      echo "path=$SHM_PATH"
      echo "size=$shm_size"
      echo "mode=$shm_mode"

      if [ "$shm_size" != "8192" ]; then
        echo "shm_size_invalid"
        doctor_failed=1
      fi

      if [ "$shm_mode" != "644" ]; then
        echo "shm_mode_invalid"
        doctor_failed=1
      fi
    fi

    echo
    echo "=== SHM PUBLICATION ==="

    if ! probe_shm; then
      echo "shm_publication_probe_failed"
      doctor_failed=1
    fi

    echo

    if [ "$doctor_failed" -ne 0 ]; then
      echo "DOCTOR=FAIL"
      exit 1
    fi

    echo "DOCTOR=PASS"
    ;;

  version)
    echo \
      "GAL-2 Node v1.0.0-rc10 Linux ARM64 release candidate"
    ;;

  *)
    usage
    exit 2
    ;;
esac
