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

DOMAIN="${GODADDY_DOMAIN:-bytelyst.com}"
TTL="${GODADDY_DNS_TTL:-600}"
TARGET_IP="${GODADDY_DNS_TARGET_IP:-}"
AUTO_IP=false
DRY_RUN=false
VALIDATE=false
HOSTS=("api" "gitea" "admin" "tracker" "llmlab" "ollama")

CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/godaddypy/credentials.yaml"

usage() {
  cat <<'USAGE'
Upsert ByteLyst GoDaddy A records for the Azure VM cutover.

Usage:
  scripts/godaddy-sync-bytelyst-dns.sh [options]

Options:
  --ip <address>         Target IPv4 address for all managed A records
  --auto-ip              Detect the current public IP with api.ipify.org
  --domain <domain>      GoDaddy zone to update (default: bytelyst.com)
  --ttl <seconds>        TTL for the managed A records (default: 600)
  --hosts <csv>          Hostnames to manage (default: api,gitea,admin,tracker,llmlab,ollama)
  --validate             Run dig validation after changes
  --dry-run              Print the API operations without applying them
  -h, --help             Show help

Credentials:
  - Preferred: GODADDY_API_KEY and GODADDY_API_SECRET
  - Fallback: ~/.config/godaddypy/credentials.yaml

Examples:
  scripts/godaddy-sync-bytelyst-dns.sh --ip 20.81.12.34 --validate
  scripts/godaddy-sync-bytelyst-dns.sh --auto-ip --dry-run
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --ip)
      TARGET_IP="${2:-}"
      shift 2
      ;;
    --auto-ip)
      AUTO_IP=true
      shift
      ;;
    --domain)
      DOMAIN="${2:-}"
      shift 2
      ;;
    --ttl)
      TTL="${2:-}"
      shift 2
      ;;
    --hosts)
      IFS=',' read -r -a HOSTS <<<"${2:-}"
      shift 2
      ;;
    --validate)
      VALIDATE=true
      shift
      ;;
    --dry-run)
      DRY_RUN=true
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown arg: $1" >&2
      usage
      exit 2
      ;;
  esac
done

trim() {
  local value="$1"
  value="${value#"${value%%[![:space:]]*}"}"
  value="${value%"${value##*[![:space:]]}"}"
  printf '%s' "$value"
}

load_credential_from_file() {
  local key_name="$1"

  if [[ ! -f "$CONFIG_FILE" ]]; then
    return 1
  fi

  sed -nE "s/^[[:space:]]*${key_name}:[[:space:]]*['\"]?([^'\"]+)['\"]?[[:space:]]*$/\\1/p" "$CONFIG_FILE" | head -n 1
}

GODADDY_API_KEY="${GODADDY_API_KEY:-}"
GODADDY_API_SECRET="${GODADDY_API_SECRET:-}"

if [[ -z "$GODADDY_API_KEY" ]]; then
  GODADDY_API_KEY="$(load_credential_from_file key || true)"
fi

if [[ -z "$GODADDY_API_SECRET" ]]; then
  GODADDY_API_SECRET="$(load_credential_from_file secret || true)"
fi

if [[ -z "$GODADDY_API_KEY" || -z "$GODADDY_API_SECRET" ]]; then
  echo "Missing GoDaddy credentials. Set GODADDY_API_KEY and GODADDY_API_SECRET, or configure $CONFIG_FILE." >&2
  exit 2
fi

if [[ "$AUTO_IP" == true ]]; then
  TARGET_IP="$(curl -fsS https://api.ipify.org)"
fi

if [[ -z "$TARGET_IP" ]]; then
  echo "Missing target IP. Use --ip <address> or --auto-ip." >&2
  exit 2
fi

if [[ ! "$TARGET_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
  echo "Target IP does not look like an IPv4 address: $TARGET_IP" >&2
  exit 2
fi

if [[ ! "$TTL" =~ ^[0-9]+$ ]]; then
  echo "TTL must be numeric: $TTL" >&2
  exit 2
fi

if ! command -v curl >/dev/null 2>&1; then
  echo "curl is required." >&2
  exit 1
fi

api_request() {
  local method="$1"
  local path="$2"
  local body="${3:-}"

  local -a curl_args=(
    -fsS
    -X "$method"
    -H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}"
    -H "Accept: application/json"
    "https://api.godaddy.com${path}"
  )

  if [[ -n "$body" ]]; then
    curl_args+=(-H "Content-Type: application/json" --data "$body")
  fi

  curl "${curl_args[@]}"
}

printf 'Domain: %s\n' "$DOMAIN"
printf 'Target IP: %s\n' "$TARGET_IP"
printf 'TTL: %s\n' "$TTL"
printf 'Hosts: %s\n' "$(IFS=,; printf '%s' "${HOSTS[*]}")"

for raw_host in "${HOSTS[@]}"; do
  host="$(trim "$raw_host")"
  if [[ -z "$host" ]]; then
    continue
  fi

  path="/v1/domains/${DOMAIN}/records/A/${host}"
  payload=$(printf '[{"data":"%s","ttl":%s}]' "$TARGET_IP" "$TTL")

  echo
  printf 'Record: %s.%s\n' "$host" "$DOMAIN"

  if [[ "$DRY_RUN" == true ]]; then
    printf 'Dry run: PUT %s %s\n' "$path" "$payload"
    continue
  fi

  current_records="$(api_request GET "$path" || true)"
  if [[ -n "$current_records" ]]; then
    printf 'Existing A records: %s\n' "$current_records"
  else
    echo "Existing A records: none"
  fi

  api_request PUT "$path" "$payload" >/dev/null
  echo "Updated A record."
done

if [[ "$VALIDATE" == true ]]; then
  echo
  echo "Validation:"
  if ! command -v dig >/dev/null 2>&1; then
    echo "dig not found; skipping DNS validation." >&2
    exit 0
  fi

  for raw_host in "${HOSTS[@]}"; do
    host="$(trim "$raw_host")"
    if [[ -z "$host" ]]; then
      continue
    fi

    resolved_ip="$(dig +short "${host}.${DOMAIN}" | tail -n 1)"
    printf '%s.%s -> %s\n' "$host" "$DOMAIN" "${resolved_ip:-<no answer>}"
  done
fi
