#!/usr/bin/env bash
# =============================================================================
# onx-pdns-zone-verify — PowerDNS zone read-only smoke test
# v87 Agent 4
# =============================================================================
#
# Bir domain için zone'un PowerDNS DB'sinde olup olmadığını, kayıt sayısını,
# SOA serial'ini ve canlı `dig` ile resolver yanıtını raporlar.
#
# YAN ETKİSİZ — sadece SELECT + dig. Üretimde panel "DNS Sağlık" widget'ı veya
# admin diagnostic tool'undan çağrılır.
#
# Stdin JSON:
#   {
#     "domain": "bisaglik.com",     // REQUIRED
#     "ns_addr": "127.0.0.1"        // OPSIYONEL; default: 127.0.0.1 (panel sunucusu)
#   }
#
# Stdout JSON:
#   {
#     "ok": true,
#     "domain": "bisaglik.com",
#     "db": {
#       "domain_id": 42,
#       "kind": "Native",
#       "record_count": 11,
#       "has_soa": true,
#       "has_ns": true,
#       "has_a_apex": true,
#       "has_mx": true,
#       "serial": "2026052701"
#     },
#     "dig": {
#       "soa": "ns3.onoxsoft.com.tr. hostmaster.bisaglik.com. 2026052701 7200 3600 1209600 3600",
#       "soa_ok": true,
#       "a_apex": "149.102.145.172",
#       "a_apex_ok": true,
#       "ns_count": 2,
#       "mx_count": 1
#     }
#   }
#
# Exit codes:
#   0 = ok (zone DB'de var)
#   1 = invalid input
#   2 = preflight fail (DB unreachable)
#   3 = zone DB'de yok (404 muadili)
# =============================================================================

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

require_root
require_cmd mysql
require_cmd jq
onx_json_input

DOMAIN="$(onx_json_field domain)"
NS_ADDR="$(onx_json_field ns_addr '127.0.0.1')"

[[ -z "$DOMAIN" ]] && onx_die 1 "domain zorunlu"
onx_validate_domain "$DOMAIN"

DOMAIN_LOWER="${DOMAIN,,}"

onx_log "pdns-zone-verify: domain=${DOMAIN_LOWER} ns_addr=${NS_ADDR}"

# ─── 1) DB lookup ────────────────────────────────────────────────────────────
DOMAIN_ROW="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT id, type, notified_serial FROM domains WHERE name='${DOMAIN_LOWER}' LIMIT 1;" \
    2>/dev/null | tail -1)"

if [[ -z "$DOMAIN_ROW" ]]; then
    # Zone DB'de yok
    jq -nc \
        --arg dom "${DOMAIN_LOWER}" \
        --arg ns "${NS_ADDR}" \
        '{ok:false,reason:"zone_not_in_pdns_db",domain:$dom,ns_addr:$ns,db:{exists:false}}'
    exit 3
fi

DOMAIN_ID="$(echo "$DOMAIN_ROW" | awk '{print $1}')"
ZONE_KIND="$(echo "$DOMAIN_ROW" | awk '{print $2}')"
NOTIFIED_SERIAL="$(echo "$DOMAIN_ROW" | awk '{print $3}')"

# Record counts
REC_COUNT="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT COUNT(*) FROM records WHERE domain_id=${DOMAIN_ID};" 2>/dev/null | tail -1)"
HAS_SOA="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT COUNT(*) FROM records WHERE domain_id=${DOMAIN_ID} AND type='SOA';" 2>/dev/null | tail -1)"
HAS_NS="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT COUNT(*) FROM records WHERE domain_id=${DOMAIN_ID} AND type='NS';" 2>/dev/null | tail -1)"
HAS_A_APEX="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT COUNT(*) FROM records WHERE domain_id=${DOMAIN_ID} AND type='A' AND name='${DOMAIN_LOWER}';" 2>/dev/null | tail -1)"
HAS_MX="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT COUNT(*) FROM records WHERE domain_id=${DOMAIN_ID} AND type='MX';" 2>/dev/null | tail -1)"

SOA_CONTENT="$(mysql_exec "${ONX_PDNS_DB}" \
    "SELECT content FROM records WHERE domain_id=${DOMAIN_ID} AND type='SOA' LIMIT 1;" 2>/dev/null | tail -1)"
SOA_SERIAL=""
if [[ -n "$SOA_CONTENT" ]]; then
    SOA_SERIAL="$(echo "$SOA_CONTENT" | awk '{print $3}')"
fi

# ─── 2) Live dig probe (best-effort, dig yoksa skip) ─────────────────────────
DIG_SOA=""
DIG_A_APEX=""
DIG_NS_COUNT=0
DIG_MX_COUNT=0
DIG_AVAILABLE=false

if command -v dig >/dev/null 2>&1; then
    DIG_AVAILABLE=true
    # +short +time=3 +tries=1 — fail-fast; üretimde DNS sağlıksızsa panel UI bloklanmasın
    DIG_SOA="$(dig @"${NS_ADDR}" "${DOMAIN_LOWER}" SOA +short +time=3 +tries=1 2>/dev/null | head -1)"
    DIG_A_APEX="$(dig @"${NS_ADDR}" "${DOMAIN_LOWER}" A +short +time=3 +tries=1 2>/dev/null | head -1)"
    DIG_NS_COUNT="$(dig @"${NS_ADDR}" "${DOMAIN_LOWER}" NS +short +time=3 +tries=1 2>/dev/null | grep -c '\.' || echo 0)"
    DIG_MX_COUNT="$(dig @"${NS_ADDR}" "${DOMAIN_LOWER}" MX +short +time=3 +tries=1 2>/dev/null | grep -c '\.' || echo 0)"
fi

SOA_OK=false
[[ -n "$DIG_SOA" ]] && SOA_OK=true

A_APEX_OK=false
[[ -n "$DIG_A_APEX" && "$DIG_A_APEX" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]] && A_APEX_OK=true

# ─── 3) JSON output ──────────────────────────────────────────────────────────
jq -nc \
    --arg dom "${DOMAIN_LOWER}" \
    --arg kind "${ZONE_KIND}" \
    --arg serial "${SOA_SERIAL}" \
    --arg notified "${NOTIFIED_SERIAL}" \
    --arg dig_soa "${DIG_SOA}" \
    --arg dig_a "${DIG_A_APEX}" \
    --arg ns_addr "${NS_ADDR}" \
    --argjson did "${DOMAIN_ID:-0}" \
    --argjson rc "${REC_COUNT:-0}" \
    --argjson soa_n "${HAS_SOA:-0}" \
    --argjson ns_n "${HAS_NS:-0}" \
    --argjson a_n "${HAS_A_APEX:-0}" \
    --argjson mx_n "${HAS_MX:-0}" \
    --argjson dig_ns "${DIG_NS_COUNT:-0}" \
    --argjson dig_mx "${DIG_MX_COUNT:-0}" \
    --argjson dig_av "${DIG_AVAILABLE}" \
    --argjson soa_ok "${SOA_OK}" \
    --argjson a_ok "${A_APEX_OK}" \
    '{
        ok: true,
        domain: $dom,
        ns_addr: $ns_addr,
        db: {
            exists: true,
            domain_id: $did,
            kind: $kind,
            record_count: $rc,
            has_soa: ($soa_n > 0),
            has_ns: ($ns_n >= 2),
            has_a_apex: ($a_n > 0),
            has_mx: ($mx_n > 0),
            serial: $serial,
            notified_serial: $notified
        },
        dig: {
            available: $dig_av,
            soa: $dig_soa,
            soa_ok: $soa_ok,
            a_apex: $dig_a,
            a_apex_ok: $a_ok,
            ns_count: $dig_ns,
            mx_count: $dig_mx
        }
    }'

exit 0
