#!/usr/bin/env bash
# onx-cert-issue — Issue a Let's Encrypt certificate via acme.sh.
#
# Input (stdin JSON):
#   domain         string   Primary domain (e.g. "example.com")
#   alt_names      array    Subject Alternative Names (e.g. ["www.example.com",
#                           "mail.example.com", "webmail.example.com", ...])
#                           cPanel AutoSSL muadili: tek multi-SAN cert tüm
#                           sistem subdomain'lerini kapsayabilir (LE 100 SAN).
#   method         string   "http-01" (default) or "dns-01"
#   webroot        string   DocumentRoot for http-01 challenge (required for http-01)
#   force          bool     Force re-issue even if cert is not expiring (default: false)
#   account_email  string   ACME account email (autossl_settings.letsencrypt_email)
#   autossl        bool     Marker — log için (default: false)
#
# Output (stdout JSON):
#   {"cert_path":..., "key_path":..., "chain_path":..., "expires_at":..., "issuer":"Let's Encrypt"}
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=exec-fail
#
# Deployed to: /usr/local/onoxsoft/bin/onx-cert-issue

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

# ── Constants ────────────────────────────────────────────────────────────────
export LE_WORKING_DIR="/etc/onoxsoft/acme.sh"
ACME_BIN="${LE_WORKING_DIR}/acme.sh"
ACME_CERT_BASE="/etc/letsencrypt/live"
ACME_WEBROOT_BASE="/var/lib/letsencrypt/.well-known/acme-challenge"

# ── Read & parse stdin ───────────────────────────────────────────────────────
INPUT=$(cat)

onx_require_json "${INPUT}"

DOMAIN=$(onx_json_get "${INPUT}" "domain")
METHOD=$(onx_json_get "${INPUT}" "method" "http-01")
WEBROOT=$(onx_json_get "${INPUT}" "webroot" "")
FORCE=$(onx_json_get_bool "${INPUT}" "force" "false")
ACCOUNT_EMAIL=$(onx_json_get "${INPUT}" "account_email" "")
AUTOSSL=$(onx_json_get_bool "${INPUT}" "autossl" "false")

# ── Input validation ─────────────────────────────────────────────────────────
onx_validate_domain "${DOMAIN}"
[[ "${METHOD}" == "http-01" || "${METHOD}" == "dns-01" ]] || \
  onx_die 1 "method must be http-01 or dns-01, got: ${METHOD}"

if [[ "${METHOD}" == "http-01" && -z "${WEBROOT}" ]]; then
  onx_die 1 "webroot is required for http-01 challenge"
fi

# ── Preflight ────────────────────────────────────────────────────────────────
[[ -f "${ACME_BIN}" && -x "${ACME_BIN}" ]] || \
  onx_die 2 "acme.sh not found or not executable: ${ACME_BIN}"

if [[ "${METHOD}" == "http-01" ]]; then
  [[ -d "${WEBROOT}" ]] || onx_die 2 "webroot directory not found: ${WEBROOT}"
  # Ensure acme-challenge directory is accessible
  mkdir -p "${ACME_WEBROOT_BASE}"
fi

# Install dir for the cert
CERT_INSTALL_DIR="${ACME_CERT_BASE}/${DOMAIN}"
mkdir -p "${CERT_INSTALL_DIR}"

# ── Build alt_names -d flags ─────────────────────────────────────────────────
DOMAIN_FLAGS=(-d "${DOMAIN}")
while IFS= read -r alt; do
  [[ -n "${alt}" ]] && DOMAIN_FLAGS+=(-d "${alt}")
done < <(onx_json_array_items "${INPUT}" "alt_names")

# ── Build acme.sh command ────────────────────────────────────────────────────
ACME_CMD=("${ACME_BIN}" --issue "${DOMAIN_FLAGS[@]}")

if [[ "${METHOD}" == "http-01" ]]; then
  ACME_CMD+=(--webroot "${WEBROOT}")
else
  # dns-01 — caller must configure DNS provider env vars upstream
  ACME_CMD+=(--dns)
fi

[[ "${FORCE}" == "true" ]] && ACME_CMD+=(--force)

# Account email — acme.sh requires it on first call per ACA, idempotent after
if [[ -n "${ACCOUNT_EMAIL}" ]]; then
  "${ACME_BIN}" --register-account --accountemail "${ACCOUNT_EMAIL}" 2>/dev/null || true
fi

# ── Issue certificate ────────────────────────────────────────────────────────
if [[ "${AUTOSSL}" == "true" ]]; then
  onx_log "AutoSSL: multi-SAN cert for ${DOMAIN} (${#DOMAIN_FLAGS[@]} domains incl. SANs)"
else
  onx_log "Running acme.sh issue for domain: ${DOMAIN}"
fi

if ! "${ACME_CMD[@]}" 2>&1 | tee -a "/var/log/onoxsoft/acme-${DOMAIN}.log"; then
  ACME_EC=$?
  # acme.sh exit code 2 = already up-to-date (not an error)
  if [[ "${ACME_EC}" -ne 2 ]]; then
    onx_die 3 "acme.sh --issue failed for ${DOMAIN} (exit ${ACME_EC})"
  fi
fi

# ── Install cert to /etc/letsencrypt/live/<domain>/ ─────────────────────────
CERT_FILE="${CERT_INSTALL_DIR}/fullchain.pem"
KEY_FILE="${CERT_INSTALL_DIR}/privkey.pem"
CHAIN_FILE="${CERT_INSTALL_DIR}/chain.pem"

INSTALL_CMD=(
  "${ACME_BIN}" --install-cert -d "${DOMAIN}"
  --cert-file       "${CERT_INSTALL_DIR}/cert.pem"
  --key-file        "${KEY_FILE}"
  --fullchain-file  "${CERT_FILE}"
  --ca-file         "${CHAIN_FILE}"
  --reloadcmd       "systemctl reload httpd 2>/dev/null || true"
)

if ! "${INSTALL_CMD[@]}" 2>&1 | tee -a "/var/log/onoxsoft/acme-${DOMAIN}.log"; then
  onx_die 3 "acme.sh --install-cert failed for ${DOMAIN}"
fi

# ── Read expiry date from cert ───────────────────────────────────────────────
EXPIRES_AT=""
if command -v openssl >/dev/null 2>&1 && [[ -f "${CERT_FILE}" ]]; then
  EXPIRES_AT=$(openssl x509 -enddate -noout -in "${CERT_FILE}" 2>/dev/null \
    | sed 's/notAfter=//' || echo "")
fi

# ── Success ──────────────────────────────────────────────────────────────────
onx_json_out \
  "cert_path"  "${CERT_FILE}" \
  "key_path"   "${KEY_FILE}" \
  "chain_path" "${CHAIN_FILE}" \
  "expires_at" "${EXPIRES_AT}" \
  "issuer"     "Let's Encrypt"
