/**
 * ManagementAuditLogRepository
 * 
 * Repository für Management Audit Logging
 * Verwaltet management_audit_log Tabelle
 */

const dbManager = require('../database/DatabaseManager');

class ManagementAuditLogRepository {
    
    /**
     * Log eine Management-Aktion
     * @param {Object} logData - Audit-Log-Daten
     * @param {string} logData.groupId - Gruppen-ID (optional)
     * @param {string} logData.managementToken - Management-Token (wird maskiert)
     * @param {string} logData.action - Aktion (validate_token, revoke_consent, etc.)
     * @param {boolean} logData.success - Erfolg
     * @param {string} logData.errorMessage - Fehlermeldung (optional)
     * @param {string} logData.ipAddress - IP-Adresse
     * @param {string} logData.userAgent - User-Agent
     * @param {Object} logData.requestData - Request-Daten (wird als JSON gespeichert)
     * @param {string} logData.sourceHost - Source Host (public/internal)
     * @param {string} logData.sourceType - Source Type (public/internal)
     * @returns {Promise<number>} ID des Log-Eintrags
     */
    async logAction(logData) {
        // Maskiere Token (zeige nur erste 8 Zeichen)
        const maskedToken = logData.managementToken 
            ? logData.managementToken.substring(0, 8) + '...' 
            : null;

        // Sanitiere Request-Daten (entferne sensible Daten)
        const sanitizedData = logData.requestData ? {
            ...logData.requestData,
            managementToken: undefined  // Token nie loggen
        } : null;

        // Prüfe ob Spalten source_host und source_type existieren
        const tableInfo = await dbManager.all(`PRAGMA table_info(management_audit_log)`);
        const hasSourceColumns = tableInfo.some(col => col.name === 'source_host');

        let query, params;
        
        if (hasSourceColumns) {
            query = `
                INSERT INTO management_audit_log 
                    (group_id, management_token, action, success, error_message, ip_address, user_agent, request_data, source_host, source_type)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            `;
            params = [
                logData.groupId || null,
                maskedToken,
                logData.action,
                logData.success ? 1 : 0,
                logData.errorMessage || null,
                logData.ipAddress || null,
                logData.userAgent || null,
                sanitizedData ? JSON.stringify(sanitizedData) : null,
                logData.sourceHost || null,
                logData.sourceType || null
            ];
        } else {
            // Fallback für alte DB-Schemas ohne source_host/source_type
            query = `
                INSERT INTO management_audit_log 
                    (group_id, management_token, action, success, error_message, ip_address, user_agent, request_data)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)
            `;
            params = [
                logData.groupId || null,
                maskedToken,
                logData.action,
                logData.success ? 1 : 0,
                logData.errorMessage || null,
                logData.ipAddress || null,
                logData.userAgent || null,
                sanitizedData ? JSON.stringify(sanitizedData) : null
            ];
        }
        
        const result = await dbManager.run(query, params);
        
        return result.lastID;
    }

    /**
     * Hole letzte N Audit-Einträge
     * @param {number} limit - Anzahl der Einträge (default: 100)
     * @returns {Promise<Array>} Array von Audit-Einträgen
     */
    async getRecentLogs(limit = 100) {
        const query = `
            SELECT 
                id,
                group_id,
                management_token,
                action,
                success,
                error_message,
                ip_address,
                user_agent,
                request_data,
                created_at
            FROM management_audit_log
            ORDER BY created_at DESC
            LIMIT ?
        `;
        
        const logs = await dbManager.all(query, [limit]);
        
        // Parse request_data JSON
        return logs.map(log => ({
            ...log,
            requestData: log.request_data ? JSON.parse(log.request_data) : null,
            request_data: undefined
        }));
    }

    /**
     * Hole Audit-Logs für eine Gruppe
     * @param {string} groupId - Gruppen-ID
     * @returns {Promise<Array>} Array von Audit-Einträgen
     */
    async getLogsByGroupId(groupId) {
        const query = `
            SELECT 
                id,
                group_id,
                management_token,
                action,
                success,
                error_message,
                ip_address,
                user_agent,
                request_data,
                created_at
            FROM management_audit_log
            WHERE group_id = ?
            ORDER BY created_at DESC
        `;
        
        const logs = await dbManager.all(query, [groupId]);
        
        return logs.map(log => ({
            ...log,
            requestData: log.request_data ? JSON.parse(log.request_data) : null,
            request_data: undefined
        }));
    }

    /**
     * Hole fehlgeschlagene Aktionen nach IP
     * @param {string} ipAddress - IP-Adresse
     * @param {number} hours - Zeitraum in Stunden (default: 24)
     * @returns {Promise<Array>} Array von fehlgeschlagenen Aktionen
     */
    async getFailedActionsByIP(ipAddress, hours = 24) {
        const query = `
            SELECT 
                id,
                group_id,
                management_token,
                action,
                error_message,
                created_at
            FROM management_audit_log
            WHERE ip_address = ?
                AND success = 0
                AND created_at >= datetime('now', '-${hours} hours')
            ORDER BY created_at DESC
        `;
        
        return await dbManager.all(query, [ipAddress]);
    }

    /**
     * Statistiken für Audit-Log
     * @returns {Promise<Object>} Statistiken
     */
    async getStatistics() {
        const query = `
            SELECT 
                COUNT(*) as totalActions,
                SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as successfulActions,
                SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) as failedActions,
                COUNT(DISTINCT group_id) as uniqueGroups,
                COUNT(DISTINCT ip_address) as uniqueIPs,
                MAX(created_at) as lastAction
            FROM management_audit_log
        `;
        
        return await dbManager.get(query);
    }

    /**
     * Lösche alte Audit-Logs (Cleanup)
     * @param {number} days - Lösche Logs älter als X Tage (default: 90)
     * @returns {Promise<number>} Anzahl gelöschter Einträge
     */
    async cleanupOldLogs(days = 90) {
        const query = `
            DELETE FROM management_audit_log
            WHERE created_at < datetime('now', '-${days} days')
        `;
        
        const result = await dbManager.run(query);
        return result.changes;
    }
}

module.exports = new ManagementAuditLogRepository();
