#!/usr/bin/env bash
#
# onx-cert-issue-dns — DNS-01 challenge ile Let's Encrypt sertifikası al.
# Wildcard (*.example.com) destekler. acme.sh dns_pdns hook'u kullanır.
#
# Stdin (JSON):
#   {
#     "domain": "example.com",                 # zorunlu
#     "wildcard": true,                        # opsiyonel, default false
#     "extra_sans": ["api.example.com"],       # opsiyonel SAN listesi
#     "username": "onx_acme01",                # cert install yolu için
#     "email": "admin@example.com"             # opsiyonel
#   }
#
# Stdout (JSON):
#   {
#     "ok":true,"domain":"example.com",
#     "sans":["example.com","*.example.com","api.example.com"],
#     "cert_path":"/etc/onoxsoft/customer-ssl/example.com.crt",
#     "expires_at":"2026-08-17T...",
#     "issuer":"Let's Encrypt"
#   }
#
# Exit codes: 0=ok, 1=invalid input, 2=preflight fail, 3=exec fail

set -uo pipefail

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

# ── Input ──────────────────────────────────────────────────────────────────
onx_json_input
DOMAIN=$(onx_json_field "domain")
WILDCARD=$(onx_json_field "wildcard" "false")
USERNAME=$(onx_json_field "username")
EMAIL=$(onx_json_field "email")
EXTRA_SANS_RAW=$(echo "${INPUT}" | jq -r '.extra_sans // [] | .[]' 2>/dev/null || echo "")

[[ -z "${DOMAIN}" ]] && onx_die 1 "domain gerekli"
[[ "${DOMAIN}" =~ ^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$ ]] \
    || onx_die 1 "geçersiz domain: ${DOMAIN}"

[[ -z "${EMAIL}" ]] && EMAIL="admin@${DOMAIN}"

# ── Preflight ──────────────────────────────────────────────────────────────
ACME_BIN=""
for candidate in \
    /usr/local/onoxsoft/acme.sh/acme.sh \
    /etc/onoxsoft/acme.sh/acme.sh \
    /root/.acme.sh/acme.sh \
    /opt/onoxsoft/acme.sh/acme.sh; do
    if [[ -x "${candidate}" ]]; then
        ACME_BIN="${candidate}"
        break
    fi
done
[[ -z "${ACME_BIN}" ]] && onx_die 2 "acme.sh kurulu değil"

ACME_HOME="$(dirname "${ACME_BIN}")"
export LE_WORKING_DIR="${ACME_HOME}"

# PDNS API key
API_KEY_FILE="/etc/onoxsoft/pdns-api.key"
[[ -f "${API_KEY_FILE}" ]] || onx_die 2 "PDNS API key yok. Önce pdns-api-enable çalıştır: ${API_KEY_FILE}"
PDNS_TOKEN=$(cat "${API_KEY_FILE}")
[[ -z "${PDNS_TOKEN}" ]] && onx_die 2 "PDNS API key boş"

# PDNS API health
PDNS_URL="http://127.0.0.1:8081"
if ! curl -s --max-time 3 -H "X-API-Key: ${PDNS_TOKEN}" "${PDNS_URL}/api/v1/servers/localhost" | jq -e '.id' >/dev/null 2>&1; then
    onx_die 2 "PDNS API erişilemiyor (${PDNS_URL}). pdns-api-enable çalıştır."
fi

# ── SAN listesi inşa et ────────────────────────────────────────────────────
declare -a SANS
SANS+=("${DOMAIN}")

if [[ "${WILDCARD}" == "true" || "${WILDCARD}" == "1" ]]; then
    SANS+=("*.${DOMAIN}")
fi

if [[ -n "${EXTRA_SANS_RAW}" ]]; then
    while IFS= read -r san; do
        [[ -z "${san}" ]] && continue
        # Basit domain validate (wildcard hariç)
        if [[ "${san}" =~ ^\*\. ]]; then
            base="${san#*.}"
            [[ "${base}" =~ ^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$ ]] || continue
        else
            [[ "${san}" =~ ^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$ ]] || continue
        fi
        SANS+=("${san}")
    done <<< "${EXTRA_SANS_RAW}"
fi

# ── Cert install yolu ──────────────────────────────────────────────────────
SSL_DIR="/etc/onoxsoft/customer-ssl"
mkdir -p "${SSL_DIR}"
chmod 711 "${SSL_DIR}"

CERT_FILE="${SSL_DIR}/${DOMAIN}.crt"
KEY_FILE="${SSL_DIR}/${DOMAIN}.key"
FULLCHAIN_FILE="${SSL_DIR}/${DOMAIN}.fullchain"

LOGFILE="/var/log/onoxsoft/cert-issue-dns-${DOMAIN}.log"
mkdir -p /var/log/onoxsoft
: > "${LOGFILE}"

# ── acme.sh ortam değişkenleri (dns_pdns hook için) ───────────────────────
export PDNS_Url="${PDNS_URL}"
export PDNS_ServerId="localhost"
export PDNS_Token="${PDNS_TOKEN}"
export PDNS_Ttl="60"  # DNS propagation hızlandırmak için kısa TTL

# Account register (idempotent)
"${ACME_BIN}" --register-account -m "${EMAIL}" --server letsencrypt >>"${LOGFILE}" 2>&1 || true

# ── Issue ──────────────────────────────────────────────────────────────────
# Tüm SAN'ları -d argümanı olarak ekle
DOMAIN_ARGS=()
for san in "${SANS[@]}"; do
    DOMAIN_ARGS+=("-d" "${san}")
done

# acme.sh dns_pdns hook ile DNS-01
"${ACME_BIN}" --issue \
    --server letsencrypt \
    --dns dns_pdns \
    --dnssleep 30 \
    "${DOMAIN_ARGS[@]}" \
    --keylength 2048 \
    --force >>"${LOGFILE}" 2>&1 \
    || onx_die 3 "acme.sh --issue başarısız (DNS-01). Log: ${LOGFILE}"

# Install
"${ACME_BIN}" --install-cert -d "${DOMAIN}" \
    --cert-file      "${CERT_FILE}" \
    --key-file       "${KEY_FILE}" \
    --fullchain-file "${FULLCHAIN_FILE}" \
    --reloadcmd      "systemctl reload httpd" >>"${LOGFILE}" 2>&1 \
    || onx_die 3 "acme.sh --install-cert başarısız. Log: ${LOGFILE}"

chmod 600 "${KEY_FILE}"
chmod 644 "${CERT_FILE}" "${FULLCHAIN_FILE}"

# ── Expiry oku ─────────────────────────────────────────────────────────────
EXPIRES_AT=""
if [[ -f "${CERT_FILE}" ]]; then
    NOT_AFTER=$(openssl x509 -enddate -noout -in "${CERT_FILE}" 2>/dev/null | sed 's/^notAfter=//')
    EXPIRES_AT=$(date -d "${NOT_AFTER}" -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "")
fi

# ── Output ─────────────────────────────────────────────────────────────────
SANS_JSON=$(printf '%s\n' "${SANS[@]}" | jq -R . | jq -s -c .)

jq -nc \
    --arg dom "${DOMAIN}" \
    --argjson sans "${SANS_JSON}" \
    --arg cert "${CERT_FILE}" \
    --arg key "${KEY_FILE}" \
    --arg chain "${FULLCHAIN_FILE}" \
    --arg exp "${EXPIRES_AT}" \
    --arg log "${LOGFILE}" \
    --argjson wild "$([[ ${WILDCARD} == 'true' || ${WILDCARD} == '1' ]] && echo true || echo false)" \
    '{ok:true,domain:$dom,sans:$sans,wildcard:$wild,cert_path:$cert,key_path:$key,fullchain_path:$chain,expires_at:$exp,issuer:"Let'\''s Encrypt",challenge:"dns-01",log_file:$log}'

exit 0
