#!/usr/bin/env bash
# onx-record-upsert — PowerDNS kaydı ekle veya guncelle
# Input:  {"zone":"example.com","name":"www.example.com","type":"A",
#           "content":"1.2.3.4","ttl":3600,"prio":0}
# Output: {"zone":...,"name":...,"type":...,"content":...,"record_id":...}

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/_lib/common.sh"

require_root
require_cmd mysql
onx_json_input

ZONE="$(onx_json_field zone)"
NAME="$(onx_json_field name)"
TYPE="$(onx_json_field type)"
CONTENT="$(onx_json_field content)"
TTL="$(onx_json_field ttl '3600')"
PRIO="$(onx_json_field prio '0')"

[[ -z "$ZONE" ]]    && onx_die 1 "zone zorunlu"
[[ -z "$NAME" ]]    && onx_die 1 "name zorunlu"
[[ -z "$TYPE" ]]    && onx_die 1 "type zorunlu"
[[ -z "$CONTENT" ]] && onx_die 1 "content zorunlu"
onx_validate_domain "$ZONE"
TYPE="${TYPE^^}"
[[ "$TYPE" =~ ^(A|AAAA|CNAME|MX|TXT|SRV|CAA|NAPTR|NS|PTR|SOA)$ ]] || \
    onx_die 1 "Gecersiz kayit tipi: '${TYPE}'"
[[ "$TTL" =~ ^[0-9]{1,10}$ ]] || onx_die 1 "Gecersiz ttl: '${TTL}'"
(( TTL > 2147483647 )) && TTL=2147483647   # PowerDNS INT taşma/absürd TTL clamp
[[ "$PRIO" =~ ^[0-9]+$ ]] || PRIO=0
(( PRIO > 65535 )) && PRIO=65535           # MX/SRV prio 16-bit aralığı

ZONE_LOWER="${ZONE,,}"
NAME_LOWER="${NAME,,}"
onx_log "record-upsert: zone=${ZONE_LOWER} name=${NAME_LOWER} type=${TYPE}"

_mycnf_tmp

DOMAIN_ID="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT id FROM domains WHERE name='${ZONE_LOWER}' LIMIT 1;" 2>/dev/null | tail -1)"
[[ -z "$DOMAIN_ID" || ! "$DOMAIN_ID" =~ ^[0-9]+$ ]] && \
    onx_die 2 "Zone bulunamadi: ${ZONE_LOWER}"

# SQL-literal escaping — name/content müşteri kontrollü; tek-tırnak literal
# breakout'unu kapat (CRIT-01). ZONE (onx_validate_domain), TYPE (enum), TTL/PRIO
# (numeric) zaten guard'lı; NAME yalnız lowercase'lendi, CONTENT serbest string.
NAME_SQL="$(onx_sql_quote "${NAME_LOWER}")"
CONTENT_SQL="$(onx_sql_quote "${CONTENT}")"

# INSERT ... ON DUPLICATE KEY UPDATE
# Unique key: (domain_id, name, type, content)
# NOT: mysql_exec_stdin kullanılıyor — bare `mysql --defaults-extra-file=$_MYCNF_TMP`
# yapsaydık outer scope'taki MAIL credentials tmpfile'ı kullanılırdı (subshell
# içinde mysql_exec ile yaratılan PDNS tmpfile dışarı propagate olmuyor).
mysql_exec_stdin "${ONX_PDNS_DB}" <<SQL
INSERT INTO records (domain_id, name, type, content, ttl, prio, disabled)
VALUES (${DOMAIN_ID}, '${NAME_SQL}', '${TYPE}', '${CONTENT_SQL}', ${TTL}, ${PRIO}, 0)
ON DUPLICATE KEY UPDATE
  content = VALUES(content),
  ttl     = VALUES(ttl),
  prio    = VALUES(prio),
  disabled = 0;
SQL
[[ $? -ne 0 ]] && onx_die 3 "Kayit upsert basarisiz: ${NAME_LOWER} ${TYPE}"

# Kayit ID
RECORD_ID="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT id FROM records WHERE domain_id=${DOMAIN_ID} AND name='${NAME_SQL}' AND type='${TYPE}' AND content='${CONTENT_SQL}' LIMIT 1;" 2>/dev/null | tail -1)"

# SOA serial bump — regex-free, full reconstruct.
# Eski versiyon REGEXP_REPLACE + back-references kullanıyordu; bash/SQL/regex
# escape zincirinde fragile, üç katmandan biri patlayınca SOA bozulup zone
# SERVFAIL veriyordu. Şimdi: mevcut SOA'dan primary_ns ve admin_email parse
# et, yeniden 7 alanlı SOA inşa et. Idempotent + escape-safe.
SOA_CURRENT="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT content FROM records WHERE domain_id=${DOMAIN_ID} AND type='SOA' LIMIT 1;" 2>/dev/null | tail -1)"
if [[ -n "${SOA_CURRENT}" ]]; then
    SOA_NS="$(echo "${SOA_CURRENT}" | awk '{print $1}')"
    SOA_ADMIN="$(echo "${SOA_CURRENT}" | awk '{print $2}')"
    [[ -z "${SOA_NS}" ]]    && SOA_NS="ns3.onoxsoft.com.tr"
    [[ -z "${SOA_ADMIN}" ]] && SOA_ADMIN="hostmaster.onoxsoft.com.tr"
    NEW_SERIAL="$(date +%Y%m%d)$(printf '%02d' "$((10#$(date +%S) % 99))")"
    NEW_SOA="${SOA_NS} ${SOA_ADMIN} ${NEW_SERIAL} 7200 3600 1209600 3600"
    # SOA_NS/SOA_ADMIN DB'den parse edildi — defense-in-depth olarak escape et.
    NEW_SOA_SQL="$(onx_sql_quote "${NEW_SOA}")"
    mysql_exec "${ONX_PDNS_DB}" \
        "UPDATE records SET content='${NEW_SOA_SQL}' WHERE domain_id=${DOMAIN_ID} AND type='SOA';" \
        2>/dev/null || true
fi

# Notify (zone Master ise)
pdns_control notify "${ZONE_LOWER}" 2>/dev/null || true

RECORD_ID="${RECORD_ID:-0}"
CONTENT_ESC="${CONTENT//\"/\\\"}"
json_ok "{\"zone\":\"${ZONE_LOWER}\",\"name\":\"${NAME_LOWER}\",\"type\":\"${TYPE}\",\"content\":\"${CONTENT_ESC}\",\"ttl\":${TTL},\"prio\":${PRIO},\"record_id\":${RECORD_ID}}"
