/**
 * Proxmox Monitoring Service
 * Pollt Proxmox API und erstellt ExternalAlerts bei Problemen
 */
const https   = require('https');
const ExternalAlert = require('../models/ExternalAlert');

const PROXMOX_HOST  = process.env.PROXMOX_HOST;  // https://192.168.0.184:8006
const PROXMOX_TOKEN = process.env.PROXMOX_TOKEN; // root@pam!monitoring=UUID

// Schwellwerte
const THRESHOLDS = {
    cpu_warn:     0.80,  // 80%
    cpu_crit:     0.90,  // 90%
    ram_warn:     0.85,  // 85%
    ram_crit:     0.95,  // 95%
    disk_warn:    0.80,  // 80%
    disk_crit:    0.90,  // 90%
    storage_warn: 0.80,
    storage_crit: 0.90,
};

function proxmoxFetch(path) {
    return new Promise((resolve, reject) => {
        const url = new URL(path, PROXMOX_HOST);
        const opts = {
            hostname: url.hostname,
            port:     url.port || 8006,
            path:     url.pathname + url.search,
            method:   'GET',
            headers:  { Authorization: `PVEAPIToken=${PROXMOX_TOKEN}` },
            rejectUnauthorized: false, // self-signed cert
        };
        const req = https.request(opts, res => {
            let d = '';
            res.on('data', c => d += c);
            res.on('end', () => {
                try { resolve(JSON.parse(d).data); }
                catch { reject(new Error('Parse error: ' + d.substring(0, 200))); }
            });
        });
        req.on('error', reject);
        req.setTimeout(10000, () => { req.destroy(); reject(new Error('Timeout')); });
        req.end();
    });
}

function existsUnacked(key) {
    try {
        const db = require('../config/database').getDatabase();
        const row = db.prepare(
            `SELECT id FROM external_alerts WHERE email_message_id = ? AND acknowledged = 0`
        ).get(key);
        return !!row;
    } catch { return false; }
}

function createAlert(data) {
    try {
        if (!existsUnacked(data.email_message_id)) {
            ExternalAlert.create(data);
            console.log(`[Proxmox] Alert: ${data.device} – ${data.message}`);
        }
    } catch (e) {
        console.error('[Proxmox] createAlert error:', e.message);
    }
}

function autoResolve(key) {
    try {
        const db = require('../config/database').getDatabase();
        db.prepare(`UPDATE external_alerts SET acknowledged = 1 WHERE email_message_id = ? AND acknowledged = 0`).run(key);
    } catch { /* ignore */ }
}

async function checkNodes() {
    const nodes = await proxmoxFetch('/api2/json/nodes');
    for (const node of nodes) {
        const cpu  = node.cpu || 0;
        const ram  = node.mem / node.maxmem;
        const name = node.node;

        // Node offline
        if (node.status !== 'online') {
            createAlert({
                source: 'proxmox', device: name, service: 'Node',
                state_transition: '? -> CRIT', severity: 'CRIT',
                message: `Node ${name} ist OFFLINE`,
                customer: 'Cereda Systems GmbH',
                email_message_id: `proxmox-node-offline-${name}`,
            });
            continue;
        } else {
            autoResolve(`proxmox-node-offline-${name}`);
        }

        // CPU
        if (cpu >= THRESHOLDS.cpu_crit) {
            createAlert({
                source: 'proxmox', device: name, service: 'CPU',
                state_transition: '? -> CRIT', severity: 'CRIT',
                message: `CPU kritisch: ${(cpu * 100).toFixed(1)}%`,
                customer: 'Cereda Systems GmbH',
                email_message_id: `proxmox-cpu-crit-${name}`,
            });
        } else {
            autoResolve(`proxmox-cpu-crit-${name}`);
            if (cpu >= THRESHOLDS.cpu_warn) {
                createAlert({
                    source: 'proxmox', device: name, service: 'CPU',
                    state_transition: '? -> WARN', severity: 'WARN',
                    message: `CPU erhöht: ${(cpu * 100).toFixed(1)}%`,
                    customer: 'Cereda Systems GmbH',
                    email_message_id: `proxmox-cpu-warn-${name}`,
                });
            } else {
                autoResolve(`proxmox-cpu-warn-${name}`);
            }
        }

        // RAM
        if (ram >= THRESHOLDS.ram_crit) {
            createAlert({
                source: 'proxmox', device: name, service: 'RAM',
                state_transition: '? -> CRIT', severity: 'CRIT',
                message: `RAM kritisch: ${(ram * 100).toFixed(1)}% (${(node.mem/1024/1024/1024).toFixed(1)}/${(node.maxmem/1024/1024/1024).toFixed(1)} GB)`,
                customer: 'Cereda Systems GmbH',
                email_message_id: `proxmox-ram-crit-${name}`,
            });
        } else {
            autoResolve(`proxmox-ram-crit-${name}`);
            if (ram >= THRESHOLDS.ram_warn) {
                createAlert({
                    source: 'proxmox', device: name, service: 'RAM',
                    state_transition: '? -> WARN', severity: 'WARN',
                    message: `RAM erhöht: ${(ram * 100).toFixed(1)}% (${(node.mem/1024/1024/1024).toFixed(1)}/${(node.maxmem/1024/1024/1024).toFixed(1)} GB)`,
                    customer: 'Cereda Systems GmbH',
                    email_message_id: `proxmox-ram-warn-${name}`,
                });
            } else {
                autoResolve(`proxmox-ram-warn-${name}`);
            }
        }
    }
}

async function checkVMs() {
    const resources = await proxmoxFetch('/api2/json/cluster/resources?type=vm');
    for (const vm of resources) {
        const id   = vm.vmid;
        const name = vm.name || `VM ${id}`;
        const node = vm.node;

        // VM/CT gestoppt aber onboot=1 (sollte laufen)
        if (vm.status === 'stopped' && vm.maxmem > 0) {
            createAlert({
                source: 'proxmox', device: name, service: `${vm.type === 'lxc' ? 'LXC' : 'VM'} ${id}`,
                state_transition: 'running -> stopped', severity: 'WARN',
                message: `${vm.type === 'lxc' ? 'Container' : 'VM'} ${name} (${id}) auf ${node} ist gestoppt`,
                customer: 'Cereda Systems GmbH',
                email_message_id: `proxmox-vm-stopped-${id}`,
            });
        } else if (vm.status === 'running') {
            autoResolve(`proxmox-vm-stopped-${id}`);

            // CPU-Last einer VM
            const cpu = vm.cpu || 0;
            if (cpu >= THRESHOLDS.cpu_crit) {
                createAlert({
                    source: 'proxmox', device: name, service: `${vm.type === 'lxc' ? 'LXC' : 'VM'} CPU`,
                    state_transition: '? -> CRIT', severity: 'CRIT',
                    message: `${name} CPU kritisch: ${(cpu * 100).toFixed(1)}%`,
                    customer: 'Cereda Systems GmbH',
                    email_message_id: `proxmox-vm-cpu-crit-${id}`,
                });
            } else {
                autoResolve(`proxmox-vm-cpu-crit-${id}`);
            }
        }
    }
}

async function checkStorage() {
    const storages = await proxmoxFetch('/api2/json/cluster/resources?type=storage');
    for (const s of storages) {
        if (!s.maxdisk || s.maxdisk === 0) continue;
        const usage = s.disk / s.maxdisk;
        const name  = `${s.storage} (${s.node})`;

        if (usage >= THRESHOLDS.storage_crit) {
            createAlert({
                source: 'proxmox', device: s.node, service: `Storage: ${s.storage}`,
                state_transition: '? -> CRIT', severity: 'CRIT',
                message: `Storage ${s.storage} kritisch: ${(usage * 100).toFixed(1)}% belegt (${(s.disk/1024/1024/1024).toFixed(0)}/${(s.maxdisk/1024/1024/1024).toFixed(0)} GB)`,
                customer: 'Cereda Systems GmbH',
                email_message_id: `proxmox-storage-crit-${s.node}-${s.storage}`,
            });
        } else {
            autoResolve(`proxmox-storage-crit-${s.node}-${s.storage}`);
            if (usage >= THRESHOLDS.storage_warn) {
                createAlert({
                    source: 'proxmox', device: s.node, service: `Storage: ${s.storage}`,
                    state_transition: '? -> WARN', severity: 'WARN',
                    message: `Storage ${s.storage} erhöht: ${(usage * 100).toFixed(1)}% belegt (${(s.disk/1024/1024/1024).toFixed(0)}/${(s.maxdisk/1024/1024/1024).toFixed(0)} GB)`,
                    customer: 'Cereda Systems GmbH',
                    email_message_id: `proxmox-storage-warn-${s.node}-${s.storage}`,
                });
            } else {
                autoResolve(`proxmox-storage-warn-${s.node}-${s.storage}`);
            }
        }
    }
}

async function checkFailedTasks() {
    try {
        const nodes = await proxmoxFetch('/api2/json/nodes');
        for (const node of nodes) {
            if (node.status !== 'online') continue;
            const tasks = await proxmoxFetch(
                `/api2/json/nodes/${node.node}/tasks?errors=1&limit=10`
            );
            for (const task of (tasks || [])) {
                // Nur Tasks der letzten 24h
                if ((Date.now() / 1000 - task.starttime) > 86400) continue;
                const key = `proxmox-task-${task.upid}`;
                createAlert({
                    source: 'proxmox', device: node.node, service: `Task: ${task.type}`,
                    state_transition: '? -> WARN', severity: 'WARN',
                    message: `Task fehlgeschlagen: ${task.type} – ${task.status || 'error'}`,
                    customer: 'Cereda Systems GmbH',
                    state_time: new Date(task.starttime * 1000).toISOString(),
                    email_message_id: key,
                });
            }
        }
    } catch { /* Tasks optional */ }
}

async function pollProxmox() {
    if (!PROXMOX_HOST || !PROXMOX_TOKEN) return;
    try {
        await Promise.all([checkNodes(), checkVMs(), checkStorage(), checkFailedTasks()]);
        console.log('[Proxmox] Poll abgeschlossen');
    } catch (e) {
        console.error('[Proxmox] Poll Fehler:', e.message);
    }
}

module.exports = { pollProxmox };
