#!/usr/bin/env bash

set -Eeuo pipefail

readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly WORKSPACE_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
readonly MODULE_ROOT="${WORKSPACE_ROOT}/module"
readonly BUILD_ROOT="${WORKSPACE_ROOT}/.builds"
readonly ENTRY_ROOT="${BUILD_ROOT}/.entries"
readonly CONFIG_ROOT="${BUILD_ROOT}/etc"

if ! command -v go >/dev/null 2>&1; then
  echo "error: Go is not installed or is not available in PATH" >&2
  exit 1
fi

if [[ ! -f "${WORKSPACE_ROOT}/go.work" ]]; then
  echo "error: go.work was not found in ${WORKSPACE_ROOT}" >&2
  exit 1
fi

export GOWORK="${WORKSPACE_ROOT}/go.work"
export GOOS=linux
export GOARCH=amd64
export CGO_ENABLED=0

modules=()
while IFS= read -r -d '' go_mod; do
  modules+=("$(dirname -- "${go_mod}")")
done < <(find "${MODULE_ROOT}" -type f -name go.mod -print0 | sort -z)

if (( ${#modules[@]} == 0 )); then
  echo "error: no service modules were found under ${MODULE_ROOT}" >&2
  exit 1
fi

mkdir -p "${BUILD_ROOT}"
mkdir -p "${ENTRY_ROOT}"

cleanup() {
  rm -rf -- "${ENTRY_ROOT}"
}
trap cleanup EXIT

echo "Building ${#modules[@]} service modules..."

for module_dir in "${modules[@]}"; do
  relative_path="${module_dir#"${MODULE_ROOT}/"}"
  artifact_name="${relative_path//\//-}"
  output="${BUILD_ROOT}/${artifact_name}"

  if [[ -f "${module_dir}/cmd/main/main.go" ]]; then
    entry_file="${module_dir}/cmd/main/main.go"
    entry_package="./cmd/main"
  elif [[ -f "${module_dir}/cmd/main.go" ]]; then
    entry_file="${module_dir}/cmd/main.go"
    entry_package="./cmd"
  else
    echo "error: service entry not found under ${module_dir}/cmd" >&2
    exit 1
  fi

  mkdir -p "$(dirname -- "${output}")"
  echo "==> ${relative_path} -> ${output#"${WORKSPACE_ROOT}/"}"

  (
    cd -- "${module_dir}"
    package_name="$(awk '$1 == "package" { print $2; exit }' "${entry_file}")"

    if [[ "${package_name}" == "main" ]]; then
      go build -trimpath -o "${output}" "${entry_package}"
    else
      module_name="$(awk '$1 == "module" { print $2; exit }' go.mod)"
      module_name="${module_name//$'\r'/}"
      wrapper_dir="${ENTRY_ROOT}/${relative_path}"
      wrapper_file="${wrapper_dir}/main.go"
      mkdir -p "${wrapper_dir}"
      printf '%s\n' \
        'package main' \
        '' \
        "import service \"${module_name}/${entry_package#./}\"" \
        '' \
        'func main() {' \
        $'\tservice.Run()' \
        '}' >"${wrapper_file}"
      go build -trimpath -o "${output}" "${wrapper_file}"
    fi
  )
done

# Copy production configuration only after every service has compiled successfully.
mkdir -p "${CONFIG_ROOT}"
config_count=0

for module_dir in "${modules[@]}"; do
  module_name="$(basename -- "${module_dir}")"
  config_name="${module_name}_prod.yaml"
  config_file="${module_dir}/etc/${config_name}"
  [[ -f "${config_file}" ]] || continue
  cp -- "${config_file}" "${CONFIG_ROOT}/${config_name}"
  ((config_count += 1))
done

echo "Copied ${config_count} production configs to ${CONFIG_ROOT}"
echo "Build completed successfully: ${BUILD_ROOT}"
