#!/bin/bash
# =============================================================================
# WOOO AIOps - 公開路由 / DNS / TLS 證據備份
# 2026-05-06 ogt + Codex: 補齊 external route reconstruction evidence。
#
# 安全原則：
#   - 只做 read-only DNS/HTTP/TLS/nginx route map 匯出，不改 DNS。
#   - 不需要 registrar/CDN token；若未設定 API token，只記錄缺口。
#   - TLS private keys 不在此腳本輸出；private keys 由 encrypted configs 備份處理。
# =============================================================================

set -euo pipefail

source "$(dirname "$0")/common.sh"

SERVICE="public-routes"
LOCAL_REPO="${BACKUP_BASE}/public-routes"
DUMP_DIR="/tmp/public-routes-backup-$$"
SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=8)
K8S_BACKUP_HOSTS="${K8S_BACKUP_HOSTS:-192.168.0.120 192.168.0.121 192.168.0.125}"

DOMAINS=(
    "awoooi.wooo.work"
    "mo.wooo.work"
    "gitea.wooo.work"
    "harbor.wooo.work"
    "registry.wooo.work"
    "sentry.wooo.work"
    "signoz.wooo.work"
    "stock.wooo.work"
    "langfuse.wooo.work"
    "bitan.wooo.work"
    "aiops.wooo.work"
)

cleanup() {
    rm -rf "${DUMP_DIR}"
}

low_priority() {
    if command -v ionice >/dev/null 2>&1; then
        ionice -c2 -n7 nice -n 10 "$@"
    else
        nice -n 10 "$@"
    fi
}

capture_cmd() {
    local label="$1"
    shift
    if "$@" > "${DUMP_DIR}/${label}.txt" 2>&1; then
        log_success "Public routes 盤點完成: ${label}"
    else
        log_warn "Public routes 盤點失敗: ${label}"
        return 1
    fi
}

capture_remote_cmd() {
    local host="$1"
    local label="$2"
    local cmd="$3"
    if ssh "${SSH_OPTS[@]}" "${host}" "${cmd}" > "${DUMP_DIR}/${label}.txt" 2>&1; then
        log_success "Public routes 遠端盤點完成: ${label}"
    else
        log_warn "Public routes 遠端盤點失敗: ${label}"
        return 1
    fi
}

capture_k8s_ingress_summary() {
    local k8s_host
    local cmd="sudo -n kubectl get ingress -A -o wide 2>/dev/null || kubectl get ingress -A -o wide"
    for k8s_host in ${K8S_BACKUP_HOSTS}; do
        if capture_remote_cmd "wooo@${k8s_host}" "cluster-k3s-ingress-summary" "${cmd}"; then
            printf 'source_host=%s\n' "${k8s_host}" > "${DUMP_DIR}/cluster-k3s-ingress-summary.source"
            return 0
        fi
    done
    return 1
}

main() {
    local start_time
    local timestamp
    local failed=0
    start_time=$(date +%s)
    timestamp=$(date "+%Y%m%d_%H%M%S")

    trap cleanup EXIT
    install -d -m 700 "${DUMP_DIR}"

    log_info "========== 開始 Public routes 備份 (${timestamp}) =========="

    {
        echo "domain,record_type,answer"
        for domain in "${DOMAINS[@]}"; do
            if command -v dig >/dev/null 2>&1; then
                for rrtype in A AAAA CNAME; do
                    dig +short "${rrtype}" "${domain}" | sed "s#^#${domain},${rrtype},#"
                done
            else
                getent ahosts "${domain}" 2>/dev/null | awk -v d="${domain}" '{print d ",A_OR_AAAA," $1}' | sort -u
            fi
        done
    } > "${DUMP_DIR}/dns-answers.csv"
    log_success "Public routes DNS answers 匯出完成"

    {
        echo "domain,http_code,total_time,remote_ip"
        for domain in "${DOMAINS[@]}"; do
            curl -k -sS -o /dev/null \
                --connect-timeout 5 \
                --max-time 10 \
                -w "${domain},%{http_code},%{time_total},%{remote_ip}\n" \
                "https://${domain}/" || echo "${domain},000,0,unreachable"
        done
    } > "${DUMP_DIR}/https-status.csv"
    log_success "Public routes HTTPS status 匯出完成"

    {
        echo "domain,not_before,not_after,issuer,subject"
        for domain in "${DOMAINS[@]}"; do
            cert_text=$(timeout 10 openssl s_client -servername "${domain}" -connect "${domain}:443" </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer -subject 2>/dev/null || true)
            not_before=$(printf "%s\n" "${cert_text}" | sed -n 's/^notBefore=//p')
            not_after=$(printf "%s\n" "${cert_text}" | sed -n 's/^notAfter=//p')
            issuer=$(printf "%s\n" "${cert_text}" | sed -n 's/^issuer=//p' | tr ',' ';')
            subject=$(printf "%s\n" "${cert_text}" | sed -n 's/^subject=//p' | tr ',' ';')
            echo "${domain},${not_before},${not_after},${issuer},${subject}"
        done
    } > "${DUMP_DIR}/tls-certificates.csv"
    log_success "Public routes TLS certificate evidence 匯出完成"

    capture_cmd "110-local-nginx-server-names" bash -lc "find /etc/nginx /home/wooo/monitoring /opt/harbor -maxdepth 4 -type f \\( -name '*.conf' -o -name '*.yml' -o -name '*.yaml' \\) -print0 2>/dev/null | xargs -0 grep -hoE 'server_name[[:space:]][^;]+' 2>/dev/null | sort -u" || true
    capture_remote_cmd "ollama@192.168.0.188" "188-nginx-server-names" "find /etc/nginx /opt/n8n /opt/open-webui /opt/litellm /opt/signoz /opt/registry -maxdepth 4 -type f \\( -name '*.conf' -o -name '*.yml' -o -name '*.yaml' \\) -print0 2>/dev/null | xargs -0 grep -hoE 'server_name[[:space:]][^;]+' 2>/dev/null | sort -u" || true
    capture_k8s_ingress_summary || true

    cat > "${DUMP_DIR}/route-export-gap.txt" <<EOF
timestamp=${timestamp}
cloud_dns_zone_export=not_configured_without_provider_token
registrar_export=manual_escrow_required
cdn_or_tunnel_export=manual_escrow_required
private_keys_policy=not_exported_here_covered_by_encrypted_configs_backup
EOF

    cat > "${DUMP_DIR}/backup-manifest.txt" <<EOF
service=public-routes
timestamp=${timestamp}
contains=dns_answers,https_status,tls_certificate_metadata,nginx_server_names,k8s_ingress_summary,route_export_gap
secret_policy=no_provider_tokens_no_tls_private_keys
failed_components=${failed}
EOF

    if [ ! -d "${LOCAL_REPO}/data" ]; then
        log_info "初始化 Restic 倉庫: ${LOCAL_REPO}"
        low_priority restic -r "${LOCAL_REPO}" init --password-file "${RESTIC_PASSWORD_FILE}" 2>&1
    fi

    log_info "建立 Public routes Restic 備份..."
    local tags
    tags=$(build_tags "${SERVICE}")
    low_priority restic -r "${LOCAL_REPO}" backup "${DUMP_DIR}" \
        --password-file "${RESTIC_PASSWORD_FILE}" \
        ${tags} \
        --tag "scope:public-routes" \
        --tag "contains:dns-http-tls-route-evidence" 2>&1

    local snapshot_id
    snapshot_id=$(restic -r "${LOCAL_REPO}" snapshots --latest 1 --json \
        --password-file "${RESTIC_PASSWORD_FILE}" 2>/dev/null | \
        python3 -c 'import json,sys; rows=json.load(sys.stdin); print(rows[-1].get("short_id","unknown") if rows else "unknown")' 2>/dev/null || echo "unknown")
    log_success "Public routes Restic 備份完成: ${snapshot_id}"

    cleanup_old_backups "${LOCAL_REPO}"

    local duration
    duration=$(($(date +%s) - start_time))
    log_success "========== Public routes 備份完成 (${duration}s) =========="
    notify_clawbot "success" "${SERVICE}" "Public routes 備份完成" "${duration}"
}

main "$@"
