#!/usr/bin/env bash

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INFRA_DIR="${INFRA_DIR:-$(cd "${SCRIPT_DIR}/.." && pwd)}"
BOOK_DIR="${BOOK_DIR:-}"
BOOK_SLUG="${BOOK_SLUG:-}"

resolve_book_dir() {
  if [[ -n "${BOOK_DIR}" ]]; then
    printf '%s\n' "${BOOK_DIR}"
    return 0
  fi
  if [[ -f "$(pwd)/book.yaml" && -f "$(pwd)/SUMMARY.md" ]]; then
    printf '%s\n' "$(pwd)"
    return 0
  fi
  printf '%s\n' 'BOOK_DIR is not set and current directory is not a book root.' >&2
  return 1
}

ensure_book_context() {
  BOOK_DIR="$(resolve_book_dir)"
  if [[ -z "${BOOK_SLUG}" ]]; then
    BOOK_SLUG="$(basename "${BOOK_DIR}")"
  fi
  export BOOK_DIR BOOK_SLUG INFRA_DIR
}

required_tools=(pandoc typst python3 go)
minimum_pandoc_version="3.1"
minimum_typst_version="0.13"
minimum_go_version="1.25.0"
supported_cjk_fonts=(
  "Noto Serif CJK SC"
  "Source Han Serif SC"
  "Songti SC"
  "Noto Sans CJK SC"
  "Source Han Sans SC"
  "PingFang SC"
)

version_ge() {
  python3 -c '
import re
import sys

def version(value):
    return tuple(int(part) for part in re.findall(r"\d+", value))

raise SystemExit(0 if version(sys.argv[1]) >= version(sys.argv[2]) else 1)
' "$1" "$2"
}

missing_tools() {
  local tool
  for tool in "${required_tools[@]}"; do
    if ! command -v "${tool}" >/dev/null 2>&1; then
      printf '%s\n' "${tool}"
    fi
  done
}

check_tool_versions() {
  local go_version pandoc_version typst_version
  pandoc_version="$(pandoc --version | sed -n '1s/^pandoc //p')"
  typst_version="$(typst --version | sed -n '1s/^typst \([0-9.]*\).*/\1/p')"
  go_version="$(go version | sed -n 's/^go version go\([0-9.]*\).*/\1/p')"
  if ! version_ge "${pandoc_version}" "${minimum_pandoc_version}"; then
    printf 'Pandoc %s or newer is required; found %s. Run `make bootstrap`.\n' \
      "${minimum_pandoc_version}" "${pandoc_version}" >&2
    return 1
  fi
  if ! version_ge "${typst_version}" "${minimum_typst_version}"; then
    printf 'Typst %s or newer is required; found %s. Run `make bootstrap`.\n' \
      "${minimum_typst_version}" "${typst_version}" >&2
    return 1
  fi
  if ! version_ge "${go_version}" "${minimum_go_version}"; then
    printf 'Go %s or newer is required; found %s. Run `make bootstrap`.\n' \
      "${minimum_go_version}" "${go_version:-unknown}" >&2
    return 1
  fi
}

has_supported_cjk_font() {
  local family fonts
  fonts="$(typst fonts)"
  for family in "${supported_cjk_fonts[@]}"; do
    if grep -Fqx -- "${family}" <<<"${fonts}"; then
      return 0
    fi
  done
  return 1
}

check_cjk_fonts() {
  if ! has_supported_cjk_font; then
    printf '%s\n' \
      'No supported Simplified Chinese font was found.' \
      'Install Noto Serif CJK SC or Source Han Serif SC; on macOS run `make bootstrap`.' >&2
    return 1
  fi
}

require_tools() {
  local missing
  missing="$(missing_tools)"
  if [[ -n "${missing}" ]]; then
    printf 'Missing required book tools:\n%s\n' "${missing}" >&2
    printf 'Run `make bootstrap` for safe installation guidance.\n' >&2
    exit 1
  fi
  check_tool_versions
  check_cjk_fonts
}

ensure_tools() {
  local missing
  missing="$(missing_tools)"
  if [[ -n "${missing}" ]]; then
    "${INFRA_DIR}/scripts/bootstrap.sh"
  elif ! check_tool_versions >/dev/null 2>&1 || ! has_supported_cjk_font; then
    "${INFRA_DIR}/scripts/bootstrap.sh"
  fi
  require_tools
}
