#!/usr/bin/env bash
# onx-csr-generate — Generate an X.509 Certificate Signing Request via openssl.
#
# Input (stdin JSON):
#   common_name    string   Primary domain (e.g. "example.com")
#   country        string   ISO 3166-1 alpha-2 (default: "TR")
#   state          string   State/Province (default: "")
#   locality       string   Locality / City (default: "")
#   organization   string   Organization name (default: "")
#   org_unit       string   Organizational Unit (default: "")
#   email          string   Contact email (default: "")
#   key_size       int|str  2048 (default) / 4096 / "ec-256" / "ec-384"
#
# Output (stdout JSON):
#   {"csr": "-----BEGIN CERTIFICATE REQUEST-----\n...",
#    "private_key": "-----BEGIN RSA PRIVATE KEY-----\n...",
#    "key_size": 2048,
#    "common_name": "example.com"}
#
# Private key is returned to the panel so it can be stored alongside the
# eventual signed cert. Tempfiles are wiped before exit.
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=exec-fail
#
# Deployed to: /usr/local/onoxsoft/bin/onx-csr-generate

set -euo pipefail

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

# ── Read & parse stdin ───────────────────────────────────────────────────────
INPUT=$(cat)
onx_require_json "${INPUT}"

COMMON_NAME=$(onx_json_get "${INPUT}" "common_name")
COUNTRY=$(onx_json_get   "${INPUT}" "country"      "TR")
STATE=$(onx_json_get     "${INPUT}" "state"        "")
LOCALITY=$(onx_json_get  "${INPUT}" "locality"     "")
ORG=$(onx_json_get       "${INPUT}" "organization" "")
OU=$(onx_json_get        "${INPUT}" "org_unit"     "")
EMAIL=$(onx_json_get     "${INPUT}" "email"        "")
KEY_SIZE=$(onx_json_get  "${INPUT}" "key_size"     "2048")

# ── Input validation ─────────────────────────────────────────────────────────
[[ -n "${COMMON_NAME}" ]] || onx_die 1 "common_name is required"

# Wildcard "*.example.com" CN'i RFC1035 regex'inden geçmez; ayrı kontrol.
if [[ "${COMMON_NAME}" == \*.* ]]; then
    onx_validate_domain "${COMMON_NAME#*.}"
else
    onx_validate_domain "${COMMON_NAME}"
fi

[[ ${#COUNTRY} -eq 2 ]] || onx_die 1 "country must be a 2-letter ISO code, got: ${COUNTRY}"

# ── Preflight ────────────────────────────────────────────────────────────────
command -v openssl >/dev/null 2>&1 || onx_die 2 "openssl not installed"

# ── Build subject string ─────────────────────────────────────────────────────
# Boş alanları subject DN'den at — openssl boş "/L=" görse hata verir.
SUBJ="/C=${COUNTRY}"
[[ -n "${STATE}"     ]] && SUBJ+="/ST=${STATE}"
[[ -n "${LOCALITY}"  ]] && SUBJ+="/L=${LOCALITY}"
[[ -n "${ORG}"       ]] && SUBJ+="/O=${ORG}"
[[ -n "${OU}"        ]] && SUBJ+="/OU=${OU}"
SUBJ+="/CN=${COMMON_NAME}"
[[ -n "${EMAIL}"     ]] && SUBJ+="/emailAddress=${EMAIL}"

# ── Tempfiles ────────────────────────────────────────────────────────────────
KEY_FILE=$(mktemp -t onx-csr-XXXXXX.key)
CSR_FILE=$(mktemp -t onx-csr-XXXXXX.csr)
trap 'rm -f "${KEY_FILE}" "${CSR_FILE}" 2>/dev/null || true' EXIT
chmod 600 "${KEY_FILE}"

# ── Generate key + CSR ───────────────────────────────────────────────────────
onx_log "CSR generate CN=${COMMON_NAME} key=${KEY_SIZE}"

case "${KEY_SIZE}" in
    ec-256)
        openssl ecparam -name prime256v1 -genkey -noout -out "${KEY_FILE}" 2>/dev/null \
            || onx_die 3 "openssl ecparam failed (P-256)"
        openssl req -new -key "${KEY_FILE}" -out "${CSR_FILE}" -subj "${SUBJ}" 2>/dev/null \
            || onx_die 3 "openssl req failed"
        ;;
    ec-384)
        openssl ecparam -name secp384r1 -genkey -noout -out "${KEY_FILE}" 2>/dev/null \
            || onx_die 3 "openssl ecparam failed (P-384)"
        openssl req -new -key "${KEY_FILE}" -out "${CSR_FILE}" -subj "${SUBJ}" 2>/dev/null \
            || onx_die 3 "openssl req failed"
        ;;
    2048|4096)
        openssl req -newkey "rsa:${KEY_SIZE}" -nodes \
            -keyout "${KEY_FILE}" -out "${CSR_FILE}" \
            -subj "${SUBJ}" 2>/dev/null \
            || onx_die 3 "openssl req failed (rsa:${KEY_SIZE})"
        ;;
    *)
        onx_die 1 "unsupported key_size: ${KEY_SIZE} (expected 2048|4096|ec-256|ec-384)"
        ;;
esac

CSR_CONTENT=$(cat "${CSR_FILE}")
KEY_CONTENT=$(cat "${KEY_FILE}")

[[ -n "${CSR_CONTENT}" && -n "${KEY_CONTENT}" ]] \
    || onx_die 3 "openssl produced empty CSR or key"

# ── Emit JSON ────────────────────────────────────────────────────────────────
# jq -n ile build et — newline'lar düzgün escape'lensin.
jq -n \
    --arg csr "${CSR_CONTENT}" \
    --arg key "${KEY_CONTENT}" \
    --arg size "${KEY_SIZE}" \
    --arg cn "${COMMON_NAME}" \
    '{csr: $csr, private_key: $key, key_size: $size, common_name: $cn}'
