#!/usr/bin/env bash

#########################################################################################
#### hetzner-cost-monitor.sh — Track and report Hetzner Cloud spending via the REST  ####
#### API. Server, volume, snapshot, and load balancer costs with alert thresholds     ####
#### Requires: bash 4+, curl, jq                                                     ####
####                                                                                 ####
#### Author: Phil Connor                                                             ####
#### Contact: contact@mylinux.work                                                   ####
#### License: MIT                                                                    ####
#### Version 1.01                                                                    ####
####                                                                                 ####
#### Usage:                                                                          ####
####   ./hetzner-cost-monitor.sh --summary                                           ####
####                                                                                 ####
#### See --help for all options.                                                     ####
#########################################################################################

set -euo pipefail

# ── Colors (pre-initialized) ─────────────────────────────────────────
RED="" GREEN="" YELLOW="" BLUE="" CYAN="" BOLD="" DIM="" RESET=""

setup_colors() {
    if [[ "${COLOR:-auto}" == "never" ]]; then
        return
    fi
    if [[ "${COLOR:-auto}" == "always" ]] || [[ -t 1 ]]; then
        RED='\033[0;31m'
        GREEN='\033[0;32m'
        YELLOW='\033[0;33m'
        BLUE='\033[0;34m'
        CYAN='\033[0;36m'
        BOLD='\033[1m'
        DIM='\033[2m'
        RESET='\033[0m'
    fi
}

# ── Logging ───────────────────────────────────────────────────────────
log()     { echo -e "${BLUE}[INFO]${RESET} $*"; }
warn()    { echo -e "${YELLOW}[WARN]${RESET} $*" >&2; }
err()     { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
verbose() { if [[ "$VERBOSE" == "true" ]]; then echo -e "${DIM}[DEBUG]${RESET} $*"; fi; }
die()     { err "$*"; exit 1; }

section_header() {
    echo ""
    echo -e "  ${BOLD}${CYAN}── $1 ──${RESET}"
    echo ""
}

field() {
    printf "  ${BOLD}%-22s${RESET} %s\n" "$1" "$2"
}

field_color() {
    printf "  ${BOLD}%-22s${RESET} %b\n" "$1" "$2"
}

elapsed() {
    local end_time
    end_time=$(date +%s)
    echo "$(( end_time - START_TIME ))s"
}

# ── Defaults ──────────────────────────────────────────────────────────
RUN_MODE=""
OUTPUT_FORMAT="${HCM_FORMAT:-table}"
ALERT_THRESHOLD="${HCM_ALERT:-0}"
VERBOSE="${VERBOSE:-false}"
COLOR="${COLOR:-auto}"

# ── Credentials ───────────────────────────────────────────────────────
HCLOUD_TOKEN="${HCLOUD_TOKEN:-}"

# ── State ─────────────────────────────────────────────────────────────
SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_NAME
START_TIME=""

# ── API helpers ──────────────────────────────────────────────────────
hcloud_api() {
    local method="$1" endpoint="$2"
    shift 2
    local attempt=0 max_attempts=3

    while (( attempt < max_attempts )); do
        local http_code
        http_code=$(curl -s -o /tmp/hcm_resp.json -w "%{http_code}" \
            -X "$method" \
            -H "Authorization: Bearer ${HCLOUD_TOKEN}" \
            -H "Content-Type: application/json" \
            "https://api.hetzner.cloud/v1${endpoint}" "$@")

        verbose "API ${method} ${endpoint} → HTTP ${http_code}"

        if [[ "$http_code" == "429" ]]; then
            ((attempt++)) || true
            local wait=$(( attempt * 5 ))
            warn "Rate limited — retrying in ${wait}s (attempt ${attempt}/${max_attempts})"
            sleep "$wait"
            continue
        fi

        if [[ "$http_code" =~ ^[45] ]]; then
            local errmsg
            errmsg=$(jq -r '.error.message // empty' /tmp/hcm_resp.json 2>/dev/null)
            [[ -n "$errmsg" ]] && verbose "API error: ${errmsg}"
        fi

        cat /tmp/hcm_resp.json
        return 0
    done

    err "API request failed after ${max_attempts} attempts: ${method} ${endpoint}"
    return 1
}

check_credentials() {
    [[ -z "$HCLOUD_TOKEN" ]] && die "HCLOUD_TOKEN not set"
}

check_deps() {
    command -v curl &>/dev/null || die "curl is required"
    command -v jq &>/dev/null || die "jq is required"
}

# ── Pagination helper ────────────────────────────────────────────────
fetch_all() {
    local endpoint="$1" key="$2"
    local page=1 per_page=50 all_data="[]"
    while true; do
        local sep="?"
        [[ "$endpoint" == *"?"* ]] && sep="&"
        local resp
        resp=$(hcloud_api GET "${endpoint}${sep}page=${page}&per_page=${per_page}")
        local page_data
        page_data=$(echo "$resp" | jq ".${key} // []" 2>/dev/null)
        local page_count
        page_count=$(echo "$page_data" | jq 'length' 2>/dev/null || echo 0)
        [[ "$page_count" -eq 0 ]] && break
        all_data=$(echo -e "${all_data}\n${page_data}" | jq -s 'add' 2>/dev/null)
        (( page_count < per_page )) && break
        ((page++)) || true
    done
    echo "$all_data"
}

# ── Cost calculation helpers ─────────────────────────────────────────
get_pricing() {
    hcloud_api GET "/pricing"
}

calc_server_costs() {
    local servers="$1" pricing="$2"
    local total="0"

    echo "$servers" | jq -r '.[] | "\(.server_type.name)\t\(.status)"' 2>/dev/null \
        | while IFS=$'\t' read -r stype status; do
            if [[ "$status" == "running" ]]; then
                local hourly
                hourly=$(echo "$pricing" | jq -r \
                    --arg t "$stype" \
                    '.pricing.server_types[] | select(.name == $t) | .prices[0].price_hourly.gross' \
                    2>/dev/null)
                [[ -n "$hourly" && "$hourly" != "null" ]] && echo "$hourly"
            fi
        done \
        | awk '{s+=$1} END {printf "%.2f", s * 730}'
}

# ══════════════════════════════════════════════════════════════════════
#                          SUMMARY
# ══════════════════════════════════════════════════════════════════════
do_summary() {
    local pricing
    pricing=$(get_pricing)

    local servers
    servers=$(fetch_all "/servers" "servers")
    local server_count
    server_count=$(echo "$servers" | jq 'length' 2>/dev/null || echo 0)
    local running_count
    running_count=$(echo "$servers" | jq '[.[] | select(.status == "running")] | length' 2>/dev/null || echo 0)

    local volumes
    volumes=$(fetch_all "/volumes" "volumes")
    local volume_count
    volume_count=$(echo "$volumes" | jq 'length' 2>/dev/null || echo 0)
    local volume_gb
    volume_gb=$(echo "$volumes" | jq '[.[].size] | add // 0' 2>/dev/null || echo 0)

    local images
    images=$(fetch_all "/images?type=snapshot" "images")
    local snapshot_count
    snapshot_count=$(echo "$images" | jq 'length' 2>/dev/null || echo 0)
    local snapshot_gb
    snapshot_gb=$(echo "$images" | jq '[.[].image_size // 0] | add // 0' 2>/dev/null || echo 0)

    local lbs
    lbs=$(fetch_all "/load_balancers" "load_balancers")
    local lb_count
    lb_count=$(echo "$lbs" | jq 'length' 2>/dev/null || echo 0)

    local ips
    ips=$(fetch_all "/floating_ips" "floating_ips")
    local ip_count
    ip_count=$(echo "$ips" | jq 'length' 2>/dev/null || echo 0)

    # Monthly cost estimates from pricing API
    local volume_price_gb
    volume_price_gb=$(echo "$pricing" | jq -r '.pricing.volume.price_per_gb_per_month.gross // "0"' 2>/dev/null)
    local volume_cost
    volume_cost=$(awk "BEGIN {printf \"%.2f\", ${volume_gb} * ${volume_price_gb}}")

    local snapshot_price_gb
    snapshot_price_gb=$(echo "$pricing" | jq -r '.pricing.image.price_per_gb_month.gross // "0"' 2>/dev/null)
    local snapshot_cost
    snapshot_cost=$(awk "BEGIN {printf \"%.2f\", ${snapshot_gb} * ${snapshot_price_gb}}")

    local ip_price
    ip_price=$(echo "$pricing" | jq -r '.pricing.floating_ip.price_monthly.gross // "0"' 2>/dev/null)
    local ip_cost
    ip_cost=$(awk "BEGIN {printf \"%.2f\", ${ip_count} * ${ip_price}}")

    # Server costs — sum hourly × 730 hours/month
    local server_cost="0.00"
    while IFS=$'\t' read -r stype status; do
        [[ -z "$stype" ]] && continue
        if [[ "$status" == "running" ]]; then
            local hourly
            hourly=$(echo "$pricing" | jq -r \
                --arg t "$stype" \
                '[.pricing.server_types[] | select(.name == $t) | .prices[0].price_hourly.gross][0] // "0"' \
                2>/dev/null)
            server_cost=$(awk "BEGIN {printf \"%.2f\", ${server_cost} + (${hourly} * 730)}")
        fi
    done < <(echo "$servers" | jq -r '.[] | "\(.server_type.name)\t\(.status)"' 2>/dev/null)

    # LB costs
    local lb_cost="0.00"
    while IFS= read -r lbtype; do
        [[ -z "$lbtype" ]] && continue
        local lb_hourly
        lb_hourly=$(echo "$pricing" | jq -r \
            --arg t "$lbtype" \
            '[.pricing.load_balancer_types[] | select(.name == $t) | .prices[0].price_hourly.gross][0] // "0"' \
            2>/dev/null)
        lb_cost=$(awk "BEGIN {printf \"%.2f\", ${lb_cost} + (${lb_hourly} * 730)}")
    done < <(echo "$lbs" | jq -r '.[].load_balancer_type.name // empty' 2>/dev/null)

    local total_cost
    total_cost=$(awk "BEGIN {printf \"%.2f\", ${server_cost} + ${volume_cost} + ${snapshot_cost} + ${lb_cost} + ${ip_cost}}")

    # Alert check
    local alert_triggered="false"
    if [[ "$ALERT_THRESHOLD" != "0" ]]; then
        local over
        over=$(awk "BEGIN {print (${total_cost} > ${ALERT_THRESHOLD}) ? 1 : 0}")
        [[ "$over" == "1" ]] && alert_triggered="true"
    fi

    case "$OUTPUT_FORMAT" in
        json)
            jq -n \
                --argjson servers "$server_count" \
                --argjson running "$running_count" \
                --argjson volumes "$volume_count" \
                --argjson volume_gb "$volume_gb" \
                --argjson snapshots "$snapshot_count" \
                --arg snapshot_gb "$snapshot_gb" \
                --argjson load_balancers "$lb_count" \
                --argjson floating_ips "$ip_count" \
                --arg server_cost "$server_cost" \
                --arg volume_cost "$volume_cost" \
                --arg snapshot_cost "$snapshot_cost" \
                --arg lb_cost "$lb_cost" \
                --arg ip_cost "$ip_cost" \
                --arg total_cost "$total_cost" \
                --arg alert_threshold "$ALERT_THRESHOLD" \
                --argjson alert_triggered "$alert_triggered" \
                '{
                    servers: $servers, running: $running,
                    volumes: $volumes, volume_gb: $volume_gb,
                    snapshots: $snapshots, snapshot_gb: ($snapshot_gb | tonumber),
                    load_balancers: $load_balancers, floating_ips: $floating_ips,
                    monthly_estimate: {
                        servers: $server_cost, volumes: $volume_cost,
                        snapshots: $snapshot_cost, load_balancers: $lb_cost,
                        floating_ips: $ip_cost, total: $total_cost
                    },
                    alert: { threshold: $alert_threshold, triggered: $alert_triggered }
                }'
            ;;
        prometheus)
            cat <<EOF
# HELP hetzner_cost_monthly_estimate_euros Estimated monthly cost in euros
# TYPE hetzner_cost_monthly_estimate_euros gauge
hetzner_cost_monthly_estimate_euros ${total_cost}
# HELP hetzner_cost_servers_euros Estimated monthly server cost
# TYPE hetzner_cost_servers_euros gauge
hetzner_cost_servers_euros ${server_cost}
# HELP hetzner_cost_volumes_euros Estimated monthly volume cost
# TYPE hetzner_cost_volumes_euros gauge
hetzner_cost_volumes_euros ${volume_cost}
# HELP hetzner_cost_snapshots_euros Estimated monthly snapshot cost
# TYPE hetzner_cost_snapshots_euros gauge
hetzner_cost_snapshots_euros ${snapshot_cost}
# HELP hetzner_cost_load_balancers_euros Estimated monthly load balancer cost
# TYPE hetzner_cost_load_balancers_euros gauge
hetzner_cost_load_balancers_euros ${lb_cost}
# HELP hetzner_cost_floating_ips_euros Estimated monthly floating IP cost
# TYPE hetzner_cost_floating_ips_euros gauge
hetzner_cost_floating_ips_euros ${ip_cost}
# HELP hetzner_cost_servers_total Total servers
# TYPE hetzner_cost_servers_total gauge
hetzner_cost_servers_total ${server_count}
# HELP hetzner_cost_servers_running Running servers
# TYPE hetzner_cost_servers_running gauge
hetzner_cost_servers_running ${running_count}
# HELP hetzner_cost_volumes_total Total volumes
# TYPE hetzner_cost_volumes_total gauge
hetzner_cost_volumes_total ${volume_count}
# HELP hetzner_cost_volume_gb_total Total volume storage in GB
# TYPE hetzner_cost_volume_gb_total gauge
hetzner_cost_volume_gb_total ${volume_gb}
# HELP hetzner_cost_snapshots_total Total snapshots
# TYPE hetzner_cost_snapshots_total gauge
hetzner_cost_snapshots_total ${snapshot_count}
# HELP hetzner_cost_load_balancers_total Total load balancers
# TYPE hetzner_cost_load_balancers_total gauge
hetzner_cost_load_balancers_total ${lb_count}
# HELP hetzner_cost_floating_ips_total Total floating IPs
# TYPE hetzner_cost_floating_ips_total gauge
hetzner_cost_floating_ips_total ${ip_count}
# HELP hetzner_cost_alert_triggered Whether cost alert threshold exceeded
# TYPE hetzner_cost_alert_triggered gauge
hetzner_cost_alert_triggered $([ "$alert_triggered" == "true" ] && echo 1 || echo 0)
EOF
            ;;
        *)
            section_header "Hetzner Cloud Cost Summary"

            printf "  ${BOLD}%-20s %8s %10s %12s${RESET}\n" \
                "RESOURCE" "COUNT" "SIZE" "MONTHLY €"
            printf "  %s\n" "$(printf '%.0s─' {1..54})"

            printf "  %-20s %8s %10s %12s\n" \
                "Servers (running)" "$running_count" "—" "${server_cost}"
            printf "  %-20s %8s %10s %12s\n" \
                "Servers (total)" "$server_count" "—" "—"
            printf "  %-20s %8s %10s %12s\n" \
                "Volumes" "$volume_count" "${volume_gb} GB" "${volume_cost}"
            printf "  %-20s %8s %10s %12s\n" \
                "Snapshots" "$snapshot_count" "${snapshot_gb} GB" "${snapshot_cost}"
            printf "  %-20s %8s %10s %12s\n" \
                "Load Balancers" "$lb_count" "—" "${lb_cost}"
            printf "  %-20s %8s %10s %12s\n" \
                "Floating IPs" "$ip_count" "—" "${ip_cost}"

            printf "  %s\n" "$(printf '%.0s─' {1..54})"
            printf "  ${BOLD}%-20s %8s %10s %12s${RESET}\n" \
                "TOTAL" "" "" "${total_cost}"

            if [[ "$alert_triggered" == "true" ]]; then
                echo ""
                echo -e "  ${RED}⚠ ALERT: Monthly estimate €${total_cost} exceeds threshold €${ALERT_THRESHOLD}${RESET}"
            fi
            ;;
    esac
}

# ══════════════════════════════════════════════════════════════════════
#                          BREAKDOWN
# ══════════════════════════════════════════════════════════════════════
do_breakdown() {
    local pricing
    pricing=$(get_pricing)
    local servers
    servers=$(fetch_all "/servers" "servers")
    local server_count
    server_count=$(echo "$servers" | jq 'length' 2>/dev/null || echo 0)
    [[ "$server_count" -eq 0 ]] && die "No servers found"

    case "$OUTPUT_FORMAT" in
        json)
            echo "$servers" | jq '[.[] | {
                id: .id, name: .name, status: .status,
                type: .server_type.name, location: .datacenter.location.name,
                ip: .public_net.ipv4.ip
            }]'
            ;;
        *)
            section_header "Server Cost Breakdown"

            printf "  ${BOLD}%-10s %-20s %-10s %-8s %-8s %10s${RESET}\n" \
                "ID" "NAME" "TYPE" "STATUS" "LOC" "MONTHLY €"
            printf "  %s\n" "$(printf '%.0s─' {1..70})"

            while IFS=$'\t' read -r sid sname stype status loc; do
                [[ -z "$sid" ]] && continue
                local hourly="0"
                if [[ "$status" == "running" ]]; then
                    hourly=$(echo "$pricing" | jq -r \
                        --arg t "$stype" \
                        '[.pricing.server_types[] | select(.name == $t) | .prices[0].price_hourly.gross][0] // "0"' \
                        2>/dev/null)
                fi
                local monthly
                monthly=$(awk "BEGIN {printf \"%.2f\", ${hourly} * 730}")

                local status_color="$GREEN"
                [[ "$status" != "running" ]] && status_color="$DIM"

                printf "  %-10s %-20s %-10s " "$sid" "${sname:0:18}" "$stype"
                echo -ne "${status_color}"
                printf "%-8s" "$status"
                echo -ne "${RESET}"
                printf " %-8s %10s\n" "${loc:0:6}" "$monthly"
            done < <(echo "$servers" | jq -r \
                '.[] | "\(.id)\t\(.name // "unknown")\t\(.server_type.name // "—")\t\(.status)\t\(.datacenter.location.name // "—")"' \
                2>/dev/null)

            echo ""
            field "Servers:" "$server_count"
            ;;
    esac
}

# ══════════════════════════════════════════════════════════════════════
#                          RESOURCES
# ══════════════════════════════════════════════════════════════════════
do_resources() {
    case "$OUTPUT_FORMAT" in
        json)
            local volumes snapshots lbs ips
            volumes=$(fetch_all "/volumes" "volumes")
            snapshots=$(fetch_all "/images?type=snapshot" "images")
            lbs=$(fetch_all "/load_balancers" "load_balancers")
            ips=$(fetch_all "/floating_ips" "floating_ips")
            jq -n \
                --argjson volumes "$volumes" \
                --argjson snapshots "$snapshots" \
                --argjson load_balancers "$lbs" \
                --argjson floating_ips "$ips" \
                '{volumes: $volumes, snapshots: $snapshots, load_balancers: $load_balancers, floating_ips: $floating_ips}'
            ;;
        *)
            # Volumes
            local volumes
            volumes=$(fetch_all "/volumes" "volumes")
            local vol_count
            vol_count=$(echo "$volumes" | jq 'length' 2>/dev/null || echo 0)

            if [[ "$vol_count" -gt 0 ]]; then
                section_header "Volumes"
                printf "  ${BOLD}%-12s %-20s %-8s %-10s %-8s${RESET}\n" \
                    "ID" "NAME" "SIZE" "LOCATION" "STATUS"
                printf "  %s\n" "$(printf '%.0s─' {1..60})"

                echo "$volumes" | jq -r \
                    '.[] | "\(.id)\t\(.name // "—")\t\(.size)GB\t\(.location.name // "—")\t\(.status // "—")"' \
                    2>/dev/null \
                    | while IFS=$'\t' read -r vid vname vsize vloc vstatus; do
                        printf "  %-12s %-20s %-8s %-10s %-8s\n" \
                            "$vid" "${vname:0:18}" "$vsize" "${vloc:0:8}" "$vstatus"
                    done
                echo ""
                field "Volumes:" "$vol_count"
            fi

            # Snapshots
            local snapshots
            snapshots=$(fetch_all "/images?type=snapshot" "images")
            local snap_count
            snap_count=$(echo "$snapshots" | jq 'length' 2>/dev/null || echo 0)

            if [[ "$snap_count" -gt 0 ]]; then
                section_header "Snapshots"
                printf "  ${BOLD}%-12s %-22s %-10s %-20s${RESET}\n" \
                    "ID" "DESCRIPTION" "SIZE" "CREATED"
                printf "  %s\n" "$(printf '%.0s─' {1..66})"

                echo "$snapshots" | jq -r \
                    '.[] | "\(.id)\t\(.description // "—")\t\(.image_size // 0)GB\t\(.created // "—")"' \
                    2>/dev/null \
                    | while IFS=$'\t' read -r iid idesc isize icreated; do
                        printf "  %-12s %-22s %-10s %-20s\n" \
                            "$iid" "${idesc:0:20}" "$isize" "${icreated:0:19}"
                    done
                echo ""
                field "Snapshots:" "$snap_count"
            fi

            # Floating IPs
            local ips
            ips=$(fetch_all "/floating_ips" "floating_ips")
            local ip_count
            ip_count=$(echo "$ips" | jq 'length' 2>/dev/null || echo 0)

            if [[ "$ip_count" -gt 0 ]]; then
                section_header "Floating IPs"
                printf "  ${BOLD}%-12s %-18s %-10s %-12s${RESET}\n" \
                    "ID" "IP" "TYPE" "LOCATION"
                printf "  %s\n" "$(printf '%.0s─' {1..54})"

                echo "$ips" | jq -r \
                    '.[] | "\(.id)\t\(.ip)\t\(.type)\t\(.home_location.name // "—")"' \
                    2>/dev/null \
                    | while IFS=$'\t' read -r fid fip ftype floc; do
                        printf "  %-12s %-18s %-10s %-12s\n" \
                            "$fid" "$fip" "$ftype" "$floc"
                    done
                echo ""
                field "Floating IPs:" "$ip_count"
            fi
            ;;
    esac
}

# ══════════════════════════════════════════════════════════════════════
#                          HELP
# ══════════════════════════════════════════════════════════════════════
show_help() {
    cat <<EOF
${BOLD}${SCRIPT_NAME}${RESET} — Hetzner Cloud Cost Monitor

Track and report Hetzner Cloud spending via the REST API.

${BOLD}MODES${RESET}
  --summary         Cost summary across all resources (default)
  --breakdown       Per-server cost breakdown
  --resources       List all billable resources (volumes, snapshots, IPs)

${BOLD}OPTIONS${RESET}
  --format FMT      Output: table, json, prometheus (default: table)
  --alert EUROS     Alert if monthly estimate exceeds threshold
  --verbose         Debug output
  --no-color        Disable colored output
  --help            Show this help message

${BOLD}ENVIRONMENT VARIABLES${RESET}
  HCLOUD_TOKEN      Hetzner Cloud API token (required)
  HCM_FORMAT        Default output format
  HCM_ALERT         Default alert threshold in euros
  VERBOSE           Enable verbose output (true/false)
  COLOR             Color mode: auto, always, never

${BOLD}EXAMPLES${RESET}
  # Cost summary
  ${SCRIPT_NAME} --summary

  # Per-server breakdown
  ${SCRIPT_NAME} --breakdown

  # List all billable resources
  ${SCRIPT_NAME} --resources

  # JSON output
  ${SCRIPT_NAME} --summary --format json

  # Alert if monthly cost exceeds €50
  ${SCRIPT_NAME} --summary --alert 50

  # Prometheus metrics
  ${SCRIPT_NAME} --summary --format prometheus

  # Cron — hourly cost metrics
  0 * * * * /usr/local/bin/hetzner-cost-monitor.sh --summary --format prometheus --no-color > /var/lib/node_exporter/textfile/hetzner_cost.prom 2>/dev/null

${BOLD}EXIT CODES${RESET}
  0   Success
  1   Runtime error
EOF
}

# ══════════════════════════════════════════════════════════════════════
#                          PARSE ARGS
# ══════════════════════════════════════════════════════════════════════
parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --summary)     RUN_MODE="summary"; shift ;;
            --breakdown)   RUN_MODE="breakdown"; shift ;;
            --resources)   RUN_MODE="resources"; shift ;;
            --format)      OUTPUT_FORMAT="${2:?--format requires a value}"; shift 2 ;;
            --alert)       ALERT_THRESHOLD="${2:?--alert requires a threshold}"; shift 2 ;;
            --verbose)     VERBOSE="true"; shift ;;
            --no-color)    COLOR="never"; shift ;;
            --help|-h)     setup_colors; show_help; exit 0 ;;
            *)             die "Unknown option: $1 (see --help)" ;;
        esac
    done
}

# ══════════════════════════════════════════════════════════════════════
#                          MAIN
# ══════════════════════════════════════════════════════════════════════
main() {
    parse_args "$@"
    setup_colors

    if [[ -z "$RUN_MODE" ]]; then
        RUN_MODE="summary"
    fi

    check_deps
    check_credentials

    START_TIME=$(date +%s)

    case "$RUN_MODE" in
        summary)   do_summary ;;
        breakdown) do_breakdown ;;
        resources) do_resources ;;
        *)         die "Unknown mode: ${RUN_MODE}" ;;
    esac

    if [[ "$OUTPUT_FORMAT" != "prometheus" ]]; then
        echo ""
        field "Duration:" "$(elapsed)"
    fi
}

main "$@"
