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

# Keep this script rooted at the repository so `docker compose port` resolves the
# same compose project no matter which shell location invoked `make`.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

cd "${PROJECT_ROOT}"

# Docker Desktop and Linux Docker expose published ports differently. The
# default keeps the output useful before containers are fully healthy or when
# Docker is not running yet.
published_port() {
	local service="$1"
	local container_port="$2"
	local default_port="$3"
	local published=""

	published="$(docker compose port "${service}" "${container_port}" 2>/dev/null | head -n 1 || true)"
	if [[ -z "${published}" ]]; then
		printf '%s' "${default_port}"
		return
	fi

	printf '%s' "${published##*:}"
}

# The host LAN address is useful when testing from another device on the same
# network. Docker service DNS below is still the address containers should use.
detect_lan_ip() {
	if command -v ipconfig >/dev/null 2>&1; then
		ipconfig getifaddr en0 2>/dev/null && return
		ipconfig getifaddr en1 2>/dev/null && return
	fi

	if command -v hostname >/dev/null 2>&1; then
		hostname -I 2>/dev/null | awk '{print $1}' && return
	fi

	printf '-'
}

format_address() {
	local scheme="$1"
	local host="$2"
	local port="$3"
	local path="${4:-}"

	if [[ "${host}" == "-" ]]; then
		printf '-'
		return
	fi

	case "${scheme}" in
		http|ws)
			printf '%s://%s:%s%s' "${scheme}" "${host}" "${port}" "${path}"
			;;
		grpc|tcp)
			printf '%s:%s' "${host}" "${port}"
			;;
		*)
			printf '%s:%s' "${host}" "${port}"
			;;
	esac
}

print_row() {
	local service="$1"
	local purpose="$2"
	local scheme="$3"
	local container_host="$4"
	local container_port="$5"
	local default_host_port="$6"
	local path="${7:-}"
	local host_port=""
	local local_addr=""
	local lan_addr=""
	local docker_addr=""

	host_port="$(published_port "${service}" "${container_port}" "${default_host_port}")"
	local_addr="$(format_address "${scheme}" "127.0.0.1" "${host_port}" "${path}")"
	lan_addr="$(format_address "${scheme}" "${LAN_IP}" "${host_port}" "${path}")"
	docker_addr="$(format_address "${scheme}" "${container_host}" "${container_port}" "${path}")"

	printf '%-18s %-18s %-30s %-30s %-30s\n' "${service}" "${purpose}" "${local_addr}" "${lan_addr}" "${docker_addr}"
}

LAN_IP="$(detect_lan_ip)"

printf '\nCompose service addresses\n'
printf '%-18s %-18s %-30s %-30s %-30s\n' "SERVICE" "PORT" "LOCAL" "HOST_LAN" "DOCKER_NETWORK"
printf '%-18s %-18s %-30s %-30s %-30s\n' "------------------" "------------------" "------------------------------" "------------------------------" "------------------------------"

print_row "gateway-service" "HTTP JSON" "http" "gateway-service" "13000" "13000"
print_row "room-service" "gRPC" "grpc" "room-service" "13001" "13001"
print_row "wallet-service" "gRPC" "grpc" "wallet-service" "13004" "13004"
print_row "user-service" "gRPC" "grpc" "user-service" "13005" "13005"
print_row "activity-service" "gRPC" "grpc" "activity-service" "13006" "13006"
print_row "lucky-gift-service" "gRPC" "grpc" "lucky-gift-service" "13013" "13013"
print_row "luck-gateway" "HTTP JSON" "http" "luck-gateway" "13014" "13014"
print_row "admin" "HTTP JSON" "http" "admin" "13100" "13100"
print_row "cron-service" "gRPC" "grpc" "cron-service" "13007" "13007"
print_row "robot-service" "gRPC" "grpc" "robot-service" "13011" "13011"
print_row "game-service" "gRPC" "grpc" "game-service" "13008" "13008"
print_row "notice-service" "gRPC" "grpc" "notice-service" "13009" "13009"
print_row "statistics-service" "Health" "http" "statistics-service" "13110" "13110" "/healthz/ready"

show_mq_addresses() {
	if [[ -n "${DEV_RUN_MQ+x}" ]]; then
		[[ "${DEV_RUN_MQ}" == "1" ]]
		return
	fi
	docker compose ps --status running --services 2>/dev/null | grep -Eq '^(rocketmq-namesrv|rocketmq-broker)$'
}

if show_mq_addresses; then
	print_row "rocketmq-namesrv" "NameServer" "tcp" "rocketmq-namesrv" "9876" "9876"
	print_row "rocketmq-broker" "Broker" "tcp" "rocketmq-broker" "10911" "10911"
fi
print_row "mysql" "MySQL" "tcp" "mysql" "3306" "23306"
print_row "redis" "Redis" "tcp" "redis" "6379" "13379"

printf '\nUse LOCAL from the host machine, HOST_LAN from another device on the same LAN, and DOCKER_NETWORK only between compose containers.\n'
