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

cd "$(dirname "$0")/.."
source deploy/env.sh
CONTAINER_TOOL="${CONTAINER_TOOL:-}"

AGE_KEY_FILE_CANDIDATES=(
  "${SOPS_AGE_KEY_FILE:-}"
  "$HOME/.config/age/keys.txt"
  "$PWD/creds/age-key.txt"
)
AGE_KEY_FILE=""
for candidate in "${AGE_KEY_FILE_CANDIDATES[@]}"; do
  if [[ -n "$candidate" && -f "$candidate" ]]; then
    AGE_KEY_FILE="$candidate"
    break
  fi
done
if [[ -z "$AGE_KEY_FILE" ]]; then
  AGE_KEY_FILE="$HOME/.config/age/keys.txt"
fi
AGE_RECIPIENTS=(
  "age1hkehkc2rryjl975c2mg5cghmjr54n4wjshncl292h2eg5l394fhs4uydrh"
  "age1ducvqxdzdhhluftu5hv4f2xsppmn803uh8tnnqj92v4n7nf6lprq9h3dqp"
)
ENCRYPTED_SECRETS_FILE="${ENCRYPTED_SECRETS_FILE:-$PWD/creds/secrets.enc.env}"

require_cmd() {
  local cmd="$1"
  if ! command -v "$cmd" >/dev/null 2>&1; then
    echo "Missing required tool: $cmd. Please install it before building." >&2
    exit 1
  fi
}

check_docker() {
  echo "Deprecated: check_docker is kept for compatibility. Use check_container_engine instead." >&2
  check_container_engine
}

check_container_engine() {
  if [[ -n "${SKIP_DOCKER_CHECK:-}" || -n "${SKIP_CONTAINER_BUILD:-}" ]]; then
    return
  fi

  if [[ -n "$CONTAINER_TOOL" ]]; then
    require_cmd "$CONTAINER_TOOL"
    if "$CONTAINER_TOOL" info >/dev/null 2>&1; then
      return
    fi
    echo "$CONTAINER_TOOL is installed but the daemon/service is not reachable. Start it or choose another engine via CONTAINER_TOOL." >&2
    exit 1
  fi

  for candidate in docker podman nerdctl; do
    if command -v "$candidate" >/dev/null 2>&1 && "$candidate" info >/dev/null 2>&1; then
      CONTAINER_TOOL="$candidate"
      export CONTAINER_TOOL
      return
    fi
  done

  echo "No working container engine found (checked docker, podman, nerdctl). Start one or set CONTAINER_TOOL to a reachable engine." >&2
  exit 1
}

check_age_setup() {
  if [[ -n "${SKIP_AGE_CHECK:-}" ]]; then
    return
  fi
  require_cmd sops
  local repo_age_key="$PWD/creds/age-key.txt"
  if [[ ! -f "$AGE_KEY_FILE" ]]; then
    echo "Age key file not found at $AGE_KEY_FILE. Copy $repo_age_key or set SOPS_AGE_KEY_FILE." >&2
    exit 1
  fi
  local has_key="0"
  if command -v age-keygen >/dev/null 2>&1; then
    for recipient in "${AGE_RECIPIENTS[@]}"; do
      if age-keygen -y "$AGE_KEY_FILE" 2>/dev/null | grep -q "$recipient"; then
        has_key="1"
        break
      fi
    done
  else
    # Fallback: best-effort text check for the public key comment
    for recipient in "${AGE_RECIPIENTS[@]}"; do
      if grep -q "$recipient" "$AGE_KEY_FILE"; then
        has_key="1"
        break
      fi
    done
  fi

  if [[ "$has_key" != "1" ]]; then
    echo "Age key file at $AGE_KEY_FILE does not contain any expected public key: ${AGE_RECIPIENTS[*]}." >&2
    if [[ -f "$repo_age_key" ]]; then
      cat >&2 <<EOF
Found the repository age key at $repo_age_key.
Import it with:
  mkdir -p "$(dirname "$AGE_KEY_FILE")"
  cat "$repo_age_key" >> "$AGE_KEY_FILE"
Or set: SOPS_AGE_KEY_FILE="$repo_age_key"
EOF
    else
      echo "Ensure your ~/.config/age/keys.txt includes the repo key (see creds/age-key.txt)." >&2
    fi
    exit 1
  fi

  export SOPS_AGE_KEY_FILE="${SOPS_AGE_KEY_FILE:-$AGE_KEY_FILE}"
  if [[ -f "$ENCRYPTED_SECRETS_FILE" ]]; then
    if ! sops -d "$ENCRYPTED_SECRETS_FILE" >/dev/null 2>&1; then
      echo "sops could not decrypt $ENCRYPTED_SECRETS_FILE with the configured keys." >&2
      echo "Export SOPS_AGE_KEY_FILE to point at the correct key (e.g., creds/age-key.txt)." >&2
      exit 1
    fi
  fi
}

echo "Running pre-flight checks..."
for tool in git npm; do
  require_cmd "$tool"
done
check_container_engine
check_age_setup
if [[ -z "${SKIP_DB_MIGRATION_CHECK:-}" ]]; then
  if command -v npx >/dev/null 2>&1; then
    echo "Checking for pending Prisma migrations..."
    if ! npx prisma migrate status >/dev/null 2>&1; then
      echo "Prisma migrate status failed. Ensure DATABASE_URL is set and migrations are up to date." >&2
      exit 1
    fi
  else
    echo "npx not found; skipping Prisma migration check." >&2
  fi
fi

GIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || date +%s)
BASE_TAG=${BUILD_TAG:-$GIT_SHA}

# Optional dev override: set FORCE_DEV_TAG=1 to append a timestamp without committing
if [[ -n "${FORCE_DEV_TAG:-}" ]]; then
  BASE_TAG="${BASE_TAG}-dev$(date +%s)"
fi

IMAGE_REPO="${REGISTRY}/${REGISTRY_REPO}"
IMAGE="${IMAGE_REPO}:${BASE_TAG}"
IMAGE_LATEST="${IMAGE_REPO}:latest"

echo "Building image:"
echo "  $IMAGE"
echo "  $IMAGE_LATEST"

if [[ -z "${SKIP_NPM_AUDIT:-}" ]]; then
  # npm audit (high severity and above)
  echo "Running npm audit (high)..."
  npm audit --audit-level=high || echo "npm audit reported issues above."
else
  echo "Skipping npm audit (SKIP_NPM_AUDIT set)."
fi

if [[ -n "${SKIP_CONTAINER_BUILD:-}" ]]; then
  echo "Skipping container build (SKIP_CONTAINER_BUILD set)."
  exit 0
fi

# Build
"${CONTAINER_TOOL:-docker}" build --build-arg APP_VERSION="$GIT_SHA" -t "$IMAGE" -t "$IMAGE_LATEST" .

echo "$IMAGE" > deploy/.last-image

echo "Done. Last image: $IMAGE"

# Trivy image scan (if available)
if command -v trivy >/dev/null 2>&1; then
  MIN_TRIVY_VERSION="0.56.0"
  INSTALLED_TRIVY_VERSION="$(trivy --version 2>/dev/null | head -n1 | awk '{print $2}')"
  if [[ -n "$INSTALLED_TRIVY_VERSION" ]] && [[ "$(printf '%s\n%s\n' "$MIN_TRIVY_VERSION" "$INSTALLED_TRIVY_VERSION" | sort -V | head -n1)" != "$MIN_TRIVY_VERSION" ]]; then
    echo "Trivy version $INSTALLED_TRIVY_VERSION is older than recommended $MIN_TRIVY_VERSION."
    echo "Update recommended: brew upgrade trivy   # macOS"
    echo "or:         sudo apt-get install -y trivy   # Debian/Ubuntu (Aqua repo)"
    echo "or:         curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin"
  fi

  echo "Running Trivy scan on $IMAGE ..."
  TRIVY_IGNORE_ARGS=()
  if [[ -f ".trivyignore" ]]; then
    TRIVY_IGNORE_ARGS+=(--ignorefile .trivyignore)
  fi
  trivy image --exit-code 0 "${TRIVY_IGNORE_ARGS[@]}" "$IMAGE" || true
else
  echo "Trivy not installed; skipping image scan."
fi
