import { createClient } from 'redis';
import User from '../models/community/user.js';
// dotenv wird global in server.js/app.js geladen

const EXPIRATION_TIME = 30 * 60 * 1000;

// Debug: Zeige alle Umgebungsvariablen
console.log('[redis] DEBUG - Alle Umgebungsvariablen:');
console.log('[redis] process.env.REDIS_HOST:', process.env.REDIS_HOST);
console.log('[redis] process.env.REDIS_PORT:', process.env.REDIS_PORT);
console.log('[redis] process.env.REDIS_PASSWORD:', process.env.REDIS_PASSWORD ? '***gesetzt***' : 'NICHT GESETZT');
console.log('[redis] process.env.REDIS_PASS:', process.env.REDIS_PASS ? '***gesetzt***' : 'NICHT GESETZT');
console.log('[redis] process.env.REDIS_URL:', process.env.REDIS_URL);

const redisHost = process.env.REDIS_HOST || '127.0.0.1';
const redisPort = process.env.REDIS_PORT || '6379';
const redisPassword = process.env.REDIS_PASSWORD || process.env.REDIS_PASS || undefined;
const redisUrl = process.env.REDIS_URL || `redis://${redisHost}:${redisPort}`;

console.log('[redis] Finale Redis-Konfiguration:');
console.log('[redis] redisHost:', redisHost);
console.log('[redis] redisPort:', redisPort);
console.log('[redis] redisPassword:', redisPassword ? '***gesetzt***' : 'NICHT GESETZT');
console.log('[redis] redisUrl:', redisUrl);

if (!process.env.REDIS_HOST || !process.env.REDIS_PORT) {
    console.warn(`[redis] Verwende Fallback ${redisHost}:${redisPort}`);
}
if (!process.env.REDIS_PASSWORD && !process.env.REDIS_PASS && !process.env.REDIS_URL) {
    console.warn('[redis] Kein Passwort gesetzt (REDIS_PASSWORD/REDIS_PASS) und keine REDIS_URL vorhanden. Wenn der Server Auth erfordert, schlägt dies fehl.');
}

const redisClient = createClient({
    url: redisUrl,
    password: redisPassword,
    legacyMode: false,
});

redisClient.on('error', (err) => {
    if (typeof err?.message === 'string' && err.message.includes('NOAUTH')) {
        console.error('[redis] Authentifizierungsfehler: Server verlangt Passwort. Bitte REDIS_PASSWORD/REDIS_PASS oder REDIS_URL setzen.');
    } else {
        console.error('[redis] Fehler:', err);
    }
});

redisClient.connect().catch(console.error);

const setUserSession = async (userId, sessionData) => {
    try {
        await redisClient.sendCommand(['JSON.SET', `user:${userId}`, '.', JSON.stringify(sessionData)]);
        console.log(userId, sessionData);
        const sessionDataStr = await redisClient.sendCommand(['JSON.GET', `user:${userId}`]);
        console.log(sessionDataStr);
    } catch (error) {
        console.error('Fehler beim Setzen der Benutzersitzung:', error);
    }
};

const deleteUserSession = async (userId) => {
    try {
        const result = await redisClient.del(`user:${userId}`);
        if (result === 1) {
            console.log(`Benutzersitzung für Benutzer ${userId} erfolgreich gelöscht.`);
        } else {
            console.warn(`Benutzersitzung für Benutzer ${userId} war nicht vorhanden.`);
        }
    } catch (error) {
        console.error('Fehler beim Löschen der Benutzersitzung:', error);
    }
};

const convertToOriginalType = (value) => {
    if (value === 'true') return true;
    if (value === 'false') return false;
    if (!isNaN(value) && value.trim() !== '') return Number(value);
    return value;
};

const getUserSession = async (userId) => {
    try {
        const sessionData = await redisClient.sendCommand(['JSON.GET', `user:${userId}`]);
        return JSON.parse(sessionData);
    } catch (error) {
        console.error('Fehler beim Abrufen der Benutzersitzung:', error);
        return null;
    }
};

const updateUserTimestamp = async (userId) => {
    try {
        const userKey = `user:${userId}`;
        const userExists = await redisClient.exists(userKey);
        if (userExists) {
            const sessionDataString = await redisClient.sendCommand(['JSON.GET', `user:${userId}`]);
            const sessionData = JSON.parse(sessionDataString);
            sessionData.timestamp = Date.now();
            await redisClient.sendCommand(['JSON.SET', `user:${userId}`, '.', JSON.stringify(sessionData)]);
        }
    } catch (error) {
        console.error('Fehler beim Aktualisieren des Zeitstempels:', error);
    }
};

const cleanupExpiredSessions = async () => {
    try {
        const keys = await redisClient.keys('user:*');
        const now = Date.now();

        for (const key of keys) {
            try {
                const sessionStr = await redisClient.sendCommand(['JSON.GET', key]);
                if (sessionStr) {
                    const session = JSON.parse(sessionStr);
                    if (session.timestamp && now - parseInt(session.timestamp) > EXPIRATION_TIME) {
                        const userId = key.split(':')[1];
                        await redisClient.del(key);
                        await User.update({ authCode: '' }, { where: { hashedId: userId } });
                        console.log(`Abgelaufene Sitzung für Benutzer ${userId} mit RedisJSON gelöscht.`);
                    }
                }
            } catch (error) {
                if (error.message.includes('WRONGTYPE')) {
                    console.warn(`Schlüssel ${key} ist kein JSON-Objekt, wird übersprungen.`);
                } else {
                    console.error(`Fehler beim Bereinigen für Schlüssel ${key}:`, error);
                }
            }
        }
    } catch (error) {
        console.error('Fehler beim Bereinigen abgelaufener Sitzungen mit RedisJSON:', error);
    }
};

export {
    setUserSession,
    deleteUserSession,
    getUserSession,
    updateUserTimestamp,
    cleanupExpiredSessions,
    redisClient
};
