import pool from '../db.js';

// ==============================================================================
// Void-Genesis - Heartbeat Service
// ==============================================================================
// Dieser Service pingt alle registrierten Sektoren regelmäßig an.
export const pingSectors = async () => {
    const client = await pool.connect();
    try {
        const result = await client.query(`
            SELECT 
                id, name, api_url, status, 
                online_players, current_players, planets_count,
                max_galaxies, speed_economy, research_speed, 
                fleet_speed_hostile, fleet_speed_peaceful, fleet_speed_friendly, 
                fuel_consumption_factor, fleet_to_debris_percentage, 
                defense_to_debris_percentage, fuel_included_in_debris, 
                initial_res_premium, bonus_fields
            FROM sectors 
            WHERE api_url IS NOT NULL
        `);
        const sectors = result.rows;

        for (const sector of sectors) {
            try {
                const controller = new AbortController();
                const timeoutId = setTimeout(() => controller.abort(), 3000);

                const response = await fetch(sector.api_url + '/api/health', {
                    signal: controller.signal
                });
                clearTimeout(timeoutId);

                if (response.ok) {
                    const data = await response.json();
                    if (data.status === 'ok') {
                        
                        const hasChanged = checkSectorChanges(sector, data);

                        if (hasChanged) {
                            await client.query(
                                `UPDATE sectors SET 
                                    status = 'online',
                                    online_players = $1,
                                    current_players = $2,
                                    planets_count = $3,
                                    max_galaxies = $4,
                                    speed_economy = $5,
                                    research_speed = $6,
                                    fleet_speed_hostile = $7,
                                    fleet_speed_peaceful = $8,
                                    fleet_speed_friendly = $9,
                                    fuel_consumption_factor = $10,
                                    fleet_to_debris_percentage = $11,
                                    defense_to_debris_percentage = $12,
                                    fuel_included_in_debris = $13,
                                    initial_res_premium = $14,
                                    bonus_fields = $15
                                WHERE id = $16`,
                                [
                                    data.stats.online_players,
                                    data.stats.total_players,
                                    data.stats.planets_count,
                                    data.config.max_galaxies,
                                    data.config.speed_economy,
                                    data.config.research_speed,
                                    data.config.fleet_speed_hostile,
                                    data.config.fleet_speed_peaceful,
                                    data.config.fleet_speed_friendly,
                                    data.config.fuel_consumption_factor,
                                    data.config.fleet_to_debris_percentage,
                                    data.config.defense_to_debris_percentage,
                                    data.config.fuel_included_in_debris,
                                    data.config.initial_res_premium,
                                    data.config.bonus_fields,
                                    sector.id
                                ]
                            );
                        }
                    } else {
                        if (sector.name === 'Development') {
                            console.warn(`[Heartbeat-Trace] ⚠️ Fehler: JSON-Status war nicht 'ok', sondern:`, data.status);
                        }
                        await setSectorOffline(client, sector);
                    }
                } else {
                    if (sector.name === 'Development') {
                        console.warn(`[Heartbeat-Trace] ⚠️ HTTP-Response nicht OK! Status-Code:`, response.status);
                    }
                    await setSectorOffline(client, sector);
                }
            } catch (error) {
                if (sector.name === 'Development') {
                    console.error(`[Heartbeat-Trace] ❌ Crash bei Sektor 'Development'. Grund:`, error.message);
                }
                await setSectorOffline(client, sector);
            }
        }
    } catch (error) {
        console.error('[Heartbeat] Kritischer Fehler bei der Datenbankabfrage:', error);
    } finally {
        client.release();
    }
};

/**
 * Hilfsfunktion zum Vergleichen des alten DB-Stands mit den frischen API-Daten.
 * Wir nutzen Number() und Boolean(), da PostgreSQL manche Datentypen 
 * (wie NUMERIC oder BIGINT) im Node.js-Treiber als String zurückgibt.
 */
const checkSectorChanges = (oldData, newData) => {
    // Wenn der Sektor vorher als offline oder in Wartung markiert war, 
    // muss er definitiv geupdatet werden, da er jetzt wieder erreichbar ist.
    if (oldData.status !== 'online') return true;

    // Spielerzahlen und Planeten prüfen
    if (Number(oldData.online_players) !== newData.stats.online_players) return true;
    if (Number(oldData.current_players) !== newData.stats.total_players) return true;
    if (Number(oldData.planets_count) !== newData.stats.planets_count) return true;

    // Globale Sektor-Einstellungen auf Änderungen prüfen
    if (Number(oldData.max_galaxies) !== newData.config.max_galaxies) return true;
    if (Number(oldData.speed_economy) !== newData.config.speed_economy) return true;
    if (Number(oldData.research_speed) !== newData.config.research_speed) return true;
    if (Number(oldData.fleet_speed_hostile) !== newData.config.fleet_speed_hostile) return true;
    if (Number(oldData.fleet_speed_peaceful) !== newData.config.fleet_speed_peaceful) return true;
    if (Number(oldData.fleet_speed_friendly) !== newData.config.fleet_speed_friendly) return true;
    
    // Float-Werte
    if (Number(oldData.fuel_consumption_factor) !== Number(newData.config.fuel_consumption_factor)) return true;
    if (Number(oldData.fleet_to_debris_percentage) !== newData.config.fleet_to_debris_percentage) return true;
    if (Number(oldData.defense_to_debris_percentage) !== newData.config.defense_to_debris_percentage) return true;
    
    // Boolean-Werte
    if (Boolean(oldData.fuel_included_in_debris) !== Boolean(newData.config.fuel_included_in_debris)) return true;
    
    // Start-Boni
    if (Number(oldData.initial_res_premium) !== newData.config.initial_res_premium) return true;
    if (Number(oldData.bonus_fields) !== newData.config.bonus_fields) return true;

    // Wurde kein Unterschied gefunden, geben wir false zurück
    return false;
};

/**
 * Setzt den Status eines Sektors auf 'offline'.
 * Prüft vorher, ob der Sektor nicht ohnehin schon als offline in der DB steht,
 * um auch hier sinnlose Schreibzugriffe und Checkpoint-Logs zu verhindern.
 */
const setSectorOffline = async (client, sector) => {
    if (sector.status !== 'offline') {
        await client.query(
            "UPDATE sectors SET status = 'offline' WHERE id = $1",
            [sector.id]
        );
        sector.status = 'offline';
    }
};