#!/bin/bash
#
# Script apelat de upssched pentru a gestiona evenimentele UPS
# Trimite notificari email via PVE::Notify
#
# Creat: 2025-10-06
# Actualizat: 2026-01-14 - Adaugat notificari periodice status baterie

LOGFILE=/var/log/ups-events.log
UPS_NAME="nutdev1"
TEMPLATE_DIR="/etc/pve/notification-templates/default"
HOSTNAME=$(hostname)
FQDN=$(hostname -f 2>/dev/null || hostname)
BATTERY_MONITOR_PID="/run/nut/battery-monitor.pid"

# Asigura ca fisierul de log exista si are permisiunile corecte
# Scriptul ruleaza ca user 'nut', deci fisierul trebuie sa fie writable
ensure_logfile() {
    if [ ! -f "$LOGFILE" ]; then
        touch "$LOGFILE" 2>/dev/null || sudo touch "$LOGFILE"
    fi
    if [ ! -w "$LOGFILE" ]; then
        sudo chown nut:nut "$LOGFILE" 2>/dev/null
        sudo chmod 664 "$LOGFILE" 2>/dev/null
    fi
}

ensure_logfile

log_event() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOGFILE 2>/dev/null || \
        logger -t upssched-cmd "LOG_FALLBACK: $1"
}

# Obtine status UPS
get_ups_status() {
    upsc $UPS_NAME ups.status 2>/dev/null || echo "UNKNOWN"
}

get_battery_charge() {
    upsc $UPS_NAME battery.charge 2>/dev/null || echo "0"
}

get_input_voltage() {
    upsc $UPS_NAME input.voltage 2>/dev/null || echo "0"
}

get_battery_runtime() {
    local runtime=$(upsc $UPS_NAME battery.runtime 2>/dev/null)
    if [ -n "$runtime" ] && [ "$runtime" != "0" ]; then
        echo $((runtime / 60))
    else
        echo ""
    fi
}

get_battery_voltage() {
    upsc $UPS_NAME battery.voltage 2>/dev/null || echo "0"
}

get_ups_load() {
    upsc $UPS_NAME ups.load 2>/dev/null || echo "0"
}

# Creeaza template-uri daca nu exista
create_templates() {
    mkdir -p $TEMPLATE_DIR

    cat > "$TEMPLATE_DIR/ups-power-event-subject.txt.hbs" << 'EOFTEMPLATE'
[{{ hostname }}] UPS {{ event_type }} - {{ event_title }}
EOFTEMPLATE

    cat > "$TEMPLATE_DIR/ups-power-event-body.txt.hbs" << 'EOFTEMPLATE'
========================================
UPS POWER EVENT - {{ event_title }}
========================================

Hostname: {{ hostname }}
Date: {{ event_date }}
Event: {{ event_type }}

{{ event_description }}

UPS STATUS:
-----------
Status: {{ ups_status }}
Battery Charge: {{ battery_charge }}%
Input Voltage: {{ input_voltage }}V
{{#if battery_runtime}}
Battery Runtime: {{ battery_runtime }} min
{{/if}}

{{#if action_taken}}
ACTION: {{ action_taken }}
{{/if}}

{{#if next_steps}}
NEXT STEPS: {{ next_steps }}
{{/if}}

========================================
Log: /var/log/ups-events.log
========================================
EOFTEMPLATE

    cat > "$TEMPLATE_DIR/ups-power-event-body.html.hbs" << 'EOFTEMPLATE'
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
        .container { max-width: 600px; margin: 0 auto; background: white; padding: 25px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h1 { margin-top: 0; padding-bottom: 15px; border-bottom: 3px solid #3498db; }
        .status-onbatt { color: #e67e22; border-color: #e67e22; }
        .status-online { color: #27ae60; border-color: #27ae60; }
        .status-lowbatt { color: #c0392b; border-color: #c0392b; }
        .status-shutdown { color: #8e44ad; border-color: #8e44ad; }
        .status-charging { color: #3498db; border-color: #3498db; }
        .alert-box { padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid; }
        .alert-warning { background: #fef9e7; border-color: #f39c12; }
        .alert-danger { background: #fdedec; border-color: #e74c3c; }
        .alert-success { background: #eafaf1; border-color: #2ecc71; }
        .alert-info { background: #ebf5fb; border-color: #3498db; }
        .metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 20px 0; }
        .metric { background: #ecf0f1; padding: 15px; border-radius: 5px; text-align: center; }
        .metric-label { font-size: 12px; color: #7f8c8d; text-transform: uppercase; }
        .metric-value { font-size: 24px; font-weight: bold; color: #2c3e50; margin-top: 5px; }
        .footer { margin-top: 25px; padding-top: 15px; border-top: 1px solid #ecf0f1; font-size: 12px; color: #7f8c8d; }
    </style>
</head>
<body>
    <div class="container">
        <h1 class="status-{{ event_class }}">[UPS] {{ event_title }}</h1>
        <p><strong>Hostname:</strong> {{ hostname }}<br>
        <strong>Date:</strong> {{ event_date }}<br>
        <strong>Event:</strong> {{ event_type }}</p>
        <div class="alert-box alert-{{ alert_type }}">
            <strong>{{ event_description }}</strong>
        </div>
        <h3>UPS Status</h3>
        <div class="metrics">
            <div class="metric">
                <div class="metric-label">Status</div>
                <div class="metric-value">{{ ups_status }}</div>
            </div>
            <div class="metric">
                <div class="metric-label">Battery</div>
                <div class="metric-value">{{ battery_charge }}%</div>
            </div>
            <div class="metric">
                <div class="metric-label">Input Voltage</div>
                <div class="metric-value">{{ input_voltage }}V</div>
            </div>
        </div>
        {{#if action_taken}}
        <p><strong>Action:</strong> {{ action_taken }}</p>
        {{/if}}
        {{#if next_steps}}
        <p><strong>Next Steps:</strong> {{ next_steps }}</p>
        {{/if}}
        <div class="footer">
            <p>Log: /var/log/ups-events.log<br>Proxmox UPS Monitoring</p>
        </div>
    </div>
</body>
</html>
EOFTEMPLATE

    log_event "Templates created in $TEMPLATE_DIR/"
}

# Trimite notificare email via PVE::Notify
send_notification() {
    local EVENT_TYPE="$1"
    local EVENT_TITLE="$2"
    local EVENT_DESC="$3"
    local EVENT_CLASS="$4"
    local ALERT_TYPE="$5"
    local SEVERITY="$6"
    local ACTION="$7"
    local NEXT_STEPS="$8"

    # Verifica si creeaza template-uri
    if [ ! -f "$TEMPLATE_DIR/ups-power-event-subject.txt.hbs" ]; then
        create_templates
    fi

    # Obtine status UPS
    local UPS_STATUS=$(get_ups_status)
    local BATTERY_CHARGE=$(get_battery_charge)
    local INPUT_VOLTAGE=$(get_input_voltage)
    local BATTERY_RUNTIME=$(get_battery_runtime)
    local EVENT_DATE=$(date '+%Y-%m-%d %H:%M:%S')

    log_event "Sending $SEVERITY notification: $EVENT_TITLE"

    /usr/bin/sudo /usr/bin/perl -I/usr/share/perl5 << EOFPERL 2>&1 | tee -a $LOGFILE
use strict;
use warnings;
use PVE::Notify;

my \$template_data = {
    'hostname' => '$FQDN',
    'event_date' => '$EVENT_DATE',
    'event_type' => '$EVENT_TYPE',
    'event_title' => '$EVENT_TITLE',
    'event_description' => '$EVENT_DESC',
    'event_class' => '$EVENT_CLASS',
    'alert_type' => '$ALERT_TYPE',
    'ups_status' => '$UPS_STATUS',
    'battery_charge' => '$BATTERY_CHARGE',
    'input_voltage' => '$INPUT_VOLTAGE',
    'battery_runtime' => '$BATTERY_RUNTIME',
    'action_taken' => '$ACTION',
    'next_steps' => '$NEXT_STEPS'
};

my \$fields = {
    'hostname' => '$HOSTNAME',
    'type' => 'ups-power-event'
};

eval {
    PVE::Notify::notify('$SEVERITY', 'ups-power-event', \$template_data, \$fields);
    print "Email notification sent successfully\\n";
};
if (\$@) {
    print STDERR "Failed to send notification: \$@\\n";
}
EOFPERL
}

# Porneste monitorizarea periodica a bateriei (la fiecare minut)
start_battery_monitor() {
    # Opreste monitorul existent daca exista
    stop_battery_monitor

    log_event "Starting battery discharge monitor (every 60 seconds)"

    # Porneste procesul de monitorizare in background
    (
        MINUTE=1
        while true; do
            sleep 60

            # Verifica daca UPS-ul e inca pe baterie
            STATUS=$(upsc $UPS_NAME ups.status 2>/dev/null)
            if [[ ! "$STATUS" =~ "OB" ]]; then
                log_event "Battery monitor: UPS no longer on battery, stopping monitor"
                break
            fi

            CHARGE=$(get_battery_charge)
            VOLTAGE=$(get_battery_voltage)
            RUNTIME=$(get_battery_runtime)
            LOAD=$(get_ups_load)

            log_event "Battery monitor: Minute $MINUTE - Charge: ${CHARGE}%, Voltage: ${VOLTAGE}V, Load: ${LOAD}%"

            send_notification \
                "BATTERY_STATUS" \
                "Status baterie - ${CHARGE}% (min $MINUTE)" \
                "UPS pe baterie de $MINUTE minute. Baterie: ${CHARGE}%, Voltaj: ${VOLTAGE}V, Load: ${LOAD}%${RUNTIME:+, Runtime: ${RUNTIME} min}" \
                "onbatt" \
                "warning" \
                "warning" \
                "Monitorizare descarcare" \
                "Se trimite status la fiecare minut"

            MINUTE=$((MINUTE + 1))
        done
        rm -f $BATTERY_MONITOR_PID
    ) &

    echo $! > $BATTERY_MONITOR_PID
    log_event "Battery monitor started with PID $(cat $BATTERY_MONITOR_PID)"
}

# Opreste monitorizarea periodica a bateriei
stop_battery_monitor() {
    if [ -f "$BATTERY_MONITOR_PID" ]; then
        PID=$(cat $BATTERY_MONITOR_PID)
        if [ -n "$PID" ] && kill -0 $PID 2>/dev/null; then
            log_event "Stopping battery monitor (PID $PID)"
            kill $PID 2>/dev/null
            # Asteapta putin si forteaza daca nu s-a oprit
            sleep 1
            kill -9 $PID 2>/dev/null
        fi
        rm -f $BATTERY_MONITOR_PID
    fi
}

# Trimite status incarcare baterie
send_charge_status() {
    local MINUTES="$1"
    local CHARGE=$(get_battery_charge)
    local VOLTAGE=$(get_battery_voltage)
    local INPUT=$(get_input_voltage)
    local LOAD=$(get_ups_load)

    log_event "Charge status at $MINUTES min: ${CHARGE}%, Voltage: ${VOLTAGE}V, Input: ${INPUT}V"

    send_notification \
        "CHARGING_STATUS" \
        "Incarcare baterie - ${CHARGE}% (+${MINUTES} min)" \
        "Status incarcare la $MINUTES minute dupa revenirea curentului. Baterie: ${CHARGE}%, Voltaj baterie: ${VOLTAGE}V, Tensiune intrare: ${INPUT}V, Load: ${LOAD}%" \
        "charging" \
        "info" \
        "info" \
        "Monitorizare incarcare" \
        "Bateria se incarca"
}

# Handler principal
case $1 in
    onbatt_start)
        log_event "=========================================="
        log_event "UPS EVENT: Trecere pe baterie - Timer 3 minute pornit"
        logger -t upssched-cmd "UPS switched to battery - 3 minute timer started"

        send_notification \
            "ONBATT" \
            "Trecere pe baterie" \
            "UPS a trecut pe baterie! Daca curentul nu revine in 3 minute, se va initia shutdown-ul cluster-ului." \
            "onbatt" \
            "warning" \
            "warning" \
            "Timer 3 minute pornit" \
            "Asteptare revenire curent sau shutdown automat"

        # Porneste monitorizarea periodica a bateriei
        start_battery_monitor
        ;;

    onbatt)
        log_event "=========================================="
        log_event "UPS EVENT: Pe baterie de 3 minute - Incepe shutdown orchestrat"
        logger -t upssched-cmd "UPS on battery for 3 minutes - starting orchestrated shutdown"

        # Opreste monitorizarea - urmeaza shutdown
        stop_battery_monitor

        send_notification \
            "ONBATT_TIMEOUT" \
            "Pe baterie 3 min - SHUTDOWN" \
            "UPS a fost pe baterie timp de 3 minute. Se initiaza shutdown-ul orchestrat al cluster-ului." \
            "onbatt" \
            "danger" \
            "error" \
            "Pornire shutdown orchestrat cluster" \
            "Toate nodurile se vor opri in ordine"

        /usr/local/bin/ups-shutdown-cluster.sh &
        ;;

    online)
        log_event "=========================================="
        log_event "UPS EVENT: Curent revenit - UPS online"
        logger -t upssched-cmd "Power restored - UPS back online"

        # Opreste monitorizarea descarcarii
        stop_battery_monitor

        send_notification \
            "ONLINE" \
            "Curent revenit - OK" \
            "Curentul electric a revenit. UPS functioneaza normal pe linia AC. Se vor trimite statusuri de incarcare la 5, 10 si 30 de minute." \
            "online" \
            "success" \
            "info" \
            "Sistem stabil" \
            "Monitorizare incarcare activa"
        ;;

    charge_5min)
        log_event "=========================================="
        log_event "UPS EVENT: Status incarcare la 5 minute"
        send_charge_status "5"
        ;;

    charge_10min)
        log_event "=========================================="
        log_event "UPS EVENT: Status incarcare la 10 minute"
        send_charge_status "10"
        ;;

    charge_30min)
        log_event "=========================================="
        log_event "UPS EVENT: Status incarcare la 30 minute"
        send_charge_status "30"
        ;;

    lowbatt)
        log_event "=========================================="
        log_event "UPS EVENT: BATERIE SCAZUTA - Shutdown IMEDIAT"
        logger -t upssched-cmd "UPS LOW BATTERY - immediate shutdown"

        # Opreste monitorizarea
        stop_battery_monitor

        send_notification \
            "LOWBATT" \
            "BATERIE CRITICA - SHUTDOWN IMEDIAT" \
            "UPS raporteaza baterie critica! Shutdown imediat pentru protectia datelor." \
            "lowbatt" \
            "danger" \
            "error" \
            "Shutdown imediat cluster" \
            "Sistemele se opresc ACUM"

        /usr/local/bin/ups-shutdown-cluster.sh &
        ;;

    commbad)
        log_event "=========================================="
        log_event "UPS EVENT: Comunicatie pierduta cu UPS de 30 secunde"
        logger -t upssched-cmd "Lost communication with UPS for 30 seconds"

        send_notification \
            "COMMBAD" \
            "Comunicatie pierduta cu UPS" \
            "Nu se poate comunica cu UPS-ul de 30 de secunde. Verificati conexiunea USB." \
            "commbad" \
            "warning" \
            "warning" \
            "Monitorizare activa" \
            "Verificati conexiunea fizica USB a UPS-ului"
        ;;

    *)
        log_event "UPS EVENT: Eveniment necunoscut - $1"
        logger -t upssched-cmd "Unknown UPS event: $1"
        ;;
esac
