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

root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${root}"

forge_host="${EVERY_CHANNEL_FORGE_HOST:-https://git.every.channel}"
forge_repo="${EVERY_CHANNEL_FORGE_REPO:-every-channel/every.channel}"
release_tag="${EVERY_CHANNEL_NETBOOT_RELEASE_TAG:-}"
local_tarball="${EVERY_CHANNEL_NETBOOT_TARBALL:-}"
out_root="${EVERY_CHANNEL_NETBOOT_ROOT:-tmp/netboot}"
ipxe_efi_url="${EVERY_CHANNEL_IPXE_EFI_URL:-https://boot.ipxe.org/snponly.efi}"
ipxe_efi_path="${EVERY_CHANNEL_IPXE_EFI_PATH:-}"
ipxe_efi_filename="${EVERY_CHANNEL_IPXE_EFI_FILENAME:-ipxe.efi}"
netboot_hostname="${EVERY_CHANNEL_NETBOOT_HOSTNAME:-boot.every.channel}"
http_port="${EVERY_CHANNEL_NETBOOT_HTTP_PORT:-8080}"
verify_release_checksums="${EVERY_CHANNEL_NETBOOT_VERIFY_RELEASE_CHECKSUMS:-true}"
allow_remote_ipxe="${EVERY_CHANNEL_NETBOOT_ALLOW_REMOTE_IPXE:-false}"
ipxe_efi_sha256="${EVERY_CHANNEL_IPXE_EFI_SHA256:-}"
chain_token="${EVERY_CHANNEL_NETBOOT_CHAIN_TOKEN:-}"
token="${EVERY_CHANNEL_FORGE_TOKEN:-${FORGE_TOKEN:-${CODEBERG_TOKEN:-}}}"

need_cmd() {
  local name="$1"
  if ! command -v "${name}" >/dev/null 2>&1; then
    echo "error: required command not found: ${name}" >&2
    exit 2
  fi
}

need_cmd curl
need_cmd tar
need_cmd python3

bool_norm() {
  local raw
  raw="$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')"
  case "${raw}" in
    ''|true|1|yes|y|on) echo "true" ;;
    false|0|no|n|off) echo "false" ;;
    *)
      echo "error: invalid boolean value '${1}'" >&2
      exit 2
      ;;
  esac
}

check_sha256() {
  local file_path="$1"
  local expected="$2"
  local actual

  if command -v sha256sum >/dev/null 2>&1; then
    actual="$(sha256sum "${file_path}" | awk '{print $1}')"
  elif command -v shasum >/dev/null 2>&1; then
    actual="$(shasum -a 256 "${file_path}" | awk '{print $1}')"
  else
    echo "error: checksum verification requested but no sha256 tool is available" >&2
    exit 2
  fi

  if [[ "${actual}" != "${expected}" ]]; then
    echo "error: checksum mismatch for ${file_path}" >&2
    exit 2
  fi
  echo "$(basename "${file_path}"): OK"
}

validate_chain_token() {
  local value="$1"
  if [[ -z "${value}" ]]; then
    return 0
  fi
  if [[ ! "${value}" =~ ^[A-Za-z0-9._~-]{16,128}$ ]]; then
    echo "error: EVERY_CHANNEL_NETBOOT_CHAIN_TOKEN must match [A-Za-z0-9._~-]{16,128}" >&2
    exit 2
  fi
}

allow_remote_ipxe="$(bool_norm "${allow_remote_ipxe}")"
validate_chain_token "${chain_token}"

tmp_dir="$(mktemp -d)"
cleanup() {
  rm -rf "${tmp_dir}"
}
trap cleanup EXIT

archive_path="${tmp_dir}/netboot.tar.gz"
release_asset_url=""
release_asset_name=""
checksum_asset_url=""

if [[ -n "${local_tarball}" ]]; then
  if [[ ! -f "${local_tarball}" ]]; then
    echo "error: netboot tarball not found: ${local_tarball}" >&2
    exit 2
  fi
  cp -f "${local_tarball}" "${archive_path}"
else
  api_base="${forge_host%/}/api/v1/repos/${forge_repo}"
  release_endpoint="${api_base}/releases/latest"
  if [[ -n "${release_tag}" ]]; then
    release_endpoint="${api_base}/releases/tags/${release_tag}"
  fi

  auth_args=()
  if [[ -n "${token}" ]]; then
    auth_args=(-H "Authorization: token ${token}")
  fi

  release_json="${tmp_dir}/release.json"
  curl -fsSL "${auth_args[@]}" "${release_endpoint}" -o "${release_json}"

  parsed_assets="$(
    python3 - "${release_json}" <<'PY'
import json
import sys

path = sys.argv[1]
with open(path, "r", encoding="utf-8") as f:
    data = json.load(f)

assets = data.get("assets", [])
candidates = []
for asset in assets:
    name = asset.get("name", "")
    if name.startswith("ec-runner-x86_64-netboot-") and name.endswith(".tar.gz"):
        candidates.append(asset)

if not candidates:
    sys.exit(1)

# Pick newest by release ordering if API already sorted; otherwise prefer largest id.
chosen = sorted(candidates, key=lambda x: x.get("id", 0))[-1]
checksum_asset = None
for asset in assets:
    if asset.get("name") == "SHA256SUMS.txt":
        checksum_asset = asset
        break

print(chosen.get("name", ""))
print(chosen.get("browser_download_url", ""))
print("" if checksum_asset is None else checksum_asset.get("browser_download_url", ""))
PY
  )"
  release_asset_name="$(printf '%s\n' "${parsed_assets}" | sed -n '1p')"
  release_asset_url="$(printf '%s\n' "${parsed_assets}" | sed -n '2p')"
  checksum_asset_url="$(printf '%s\n' "${parsed_assets}" | sed -n '3p')"

  if [[ -z "${release_asset_url}" ]]; then
    echo "error: unable to find x86_64 netboot asset in release" >&2
    exit 2
  fi

  curl -fsSL "${auth_args[@]}" -o "${archive_path}" "${release_asset_url}"

  verify_release_checksums_lc="$(printf '%s' "${verify_release_checksums}" | tr '[:upper:]' '[:lower:]')"
  if [[ "${verify_release_checksums_lc}" != "false" && -n "${checksum_asset_url}" ]]; then
    checksum_file="${tmp_dir}/SHA256SUMS.txt"
    curl -fsSL "${auth_args[@]}" -o "${checksum_file}" "${checksum_asset_url}"
    if command -v sha256sum >/dev/null 2>&1; then
      (
        cd "${tmp_dir}"
        grep -F " ${release_asset_name}" "${checksum_file}" | sha256sum -c -
      )
    elif command -v shasum >/dev/null 2>&1; then
      expected="$(grep -F " ${release_asset_name}" "${checksum_file}" | awk '{print $1}')"
      actual="$(shasum -a 256 "${archive_path}" | awk '{print $1}')"
      if [[ -z "${expected}" || "${expected}" != "${actual}" ]]; then
        echo "error: checksum mismatch for ${release_asset_name}" >&2
        exit 2
      fi
      echo "${release_asset_name}: OK"
    else
      echo "warning: no sha256 tool available; skipping checksum verification"
    fi
  fi
fi

http_dir="${out_root}/http"
tftp_dir="${out_root}/tftp"
rm -rf "${http_dir}"
mkdir -p "${http_dir}" "${tftp_dir}"

tar -xzf "${archive_path}" -C "${http_dir}"

for required in kernel initrd netboot.ipxe; do
  if [[ ! -f "${http_dir}/${required}" ]]; then
    echo "error: extracted netboot bundle is missing ${required}" >&2
    exit 2
  fi
done

if [[ -n "${ipxe_efi_path}" ]]; then
  if [[ ! -f "${ipxe_efi_path}" ]]; then
    echo "error: iPXE file path not found: ${ipxe_efi_path}" >&2
    exit 2
  fi
  ipxe_dest="${tftp_dir}/${ipxe_efi_filename}"
  src_resolved="$(realpath -m "${ipxe_efi_path}")"
  dst_resolved="$(realpath -m "${ipxe_dest}")"
  # When embedded iPXE already wrote to the destination path, skip self-copy.
  if [[ "${src_resolved}" != "${dst_resolved}" ]]; then
    cp -f "${ipxe_efi_path}" "${ipxe_dest}"
  fi
else
  if [[ "${allow_remote_ipxe}" != "true" ]]; then
    echo "error: remote iPXE download is disabled by default" >&2
    echo "hint: build local iPXE with ./scripts/netboot-build-ipxe.sh and set EVERY_CHANNEL_IPXE_EFI_PATH" >&2
    echo "hint: if you must download from URL, set EVERY_CHANNEL_NETBOOT_ALLOW_REMOTE_IPXE=true" >&2
    exit 2
  fi
  curl -fsSL -o "${tftp_dir}/${ipxe_efi_filename}" "${ipxe_efi_url}"
fi
if [[ -n "${ipxe_efi_sha256}" ]]; then
  check_sha256 "${tftp_dir}/${ipxe_efi_filename}" "${ipxe_efi_sha256}"
fi
cp -f "${http_dir}/netboot.ipxe" "${tftp_dir}/netboot.ipxe"

chain_url="http://${netboot_hostname}:${http_port}/netboot.ipxe"
if [[ -n "${chain_token}" ]]; then
  chain_url="${chain_url}?token=${chain_token}"
fi

cat > "${tftp_dir}/bootstrap.ipxe" <<EOF
#!ipxe
dhcp
chain ${chain_url}
EOF

echo "ok: staged netboot content"
echo "ok: http root: ${http_dir}"
echo "ok: tftp root: ${tftp_dir}"
echo "ok: boot filename: ${ipxe_efi_filename}"
echo "ok: netboot hostname: ${netboot_hostname}"
echo "ok: netboot http port: ${http_port}"
if [[ -n "${release_asset_url}" ]]; then
  echo "ok: source asset: ${release_asset_url}"
else
  echo "ok: source asset: ${local_tarball}"
fi
if [[ -n "${chain_token}" ]]; then
  echo "ok: chain token enabled"
fi
echo "hint: run sudo ./scripts/netboot-serve.sh to expose HTTP+TFTP (+ optional ProxyDHCP)"
