import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import { logger } from '../logger.js';
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from './classes.securitylogger.js';
import { RustSecurityBridge } from './classes.rustsecuritybridge.js';
import { LRUCache } from 'lru-cache';
/**
 * Reputation threshold scores
 */
export var ReputationThreshold;
(function (ReputationThreshold) {
    ReputationThreshold[ReputationThreshold["HIGH_RISK"] = 20] = "HIGH_RISK";
    ReputationThreshold[ReputationThreshold["MEDIUM_RISK"] = 50] = "MEDIUM_RISK";
    ReputationThreshold[ReputationThreshold["LOW_RISK"] = 80] = "LOW_RISK"; // Score below this is considered low risk (but not trusted)
})(ReputationThreshold || (ReputationThreshold = {}));
/**
 * IP type classifications
 */
export var IPType;
(function (IPType) {
    IPType["RESIDENTIAL"] = "residential";
    IPType["DATACENTER"] = "datacenter";
    IPType["PROXY"] = "proxy";
    IPType["TOR"] = "tor";
    IPType["VPN"] = "vpn";
    IPType["UNKNOWN"] = "unknown";
})(IPType || (IPType = {}));
/**
 * IP reputation checker — delegates DNSBL lookups to the Rust security bridge.
 * Retains LRU caching and disk persistence in TypeScript.
 */
export class IPReputationChecker {
    static instance;
    reputationCache;
    options;
    storageManager;
    static DEFAULT_OPTIONS = {
        maxCacheSize: 10000,
        cacheTTL: 24 * 60 * 60 * 1000,
        dnsblServers: [],
        highRiskThreshold: ReputationThreshold.HIGH_RISK,
        mediumRiskThreshold: ReputationThreshold.MEDIUM_RISK,
        lowRiskThreshold: ReputationThreshold.LOW_RISK,
        enableLocalCache: true,
        enableDNSBL: true,
        enableIPInfo: true
    };
    constructor(options = {}, storageManager) {
        this.options = {
            ...IPReputationChecker.DEFAULT_OPTIONS,
            ...options
        };
        this.storageManager = storageManager;
        this.reputationCache = new LRUCache({
            max: this.options.maxCacheSize,
            ttl: this.options.cacheTTL,
        });
        if (this.options.enableLocalCache) {
            this.loadCache().catch(error => {
                logger.log('error', `Failed to load IP reputation cache during initialization: ${error.message}`);
            });
        }
    }
    static getInstance(options = {}, storageManager) {
        if (!IPReputationChecker.instance) {
            IPReputationChecker.instance = new IPReputationChecker(options, storageManager);
        }
        return IPReputationChecker.instance;
    }
    /**
     * Check an IP address's reputation via the Rust bridge
     */
    async checkReputation(ip) {
        try {
            if (!this.isValidIPAddress(ip)) {
                logger.log('warn', `Invalid IP address format: ${ip}`);
                return this.createErrorResult(ip, 'Invalid IP address format');
            }
            // Check cache first
            const cachedResult = this.reputationCache.get(ip);
            if (cachedResult) {
                logger.log('info', `Using cached reputation data for IP ${ip}`, {
                    score: cachedResult.score,
                    isSpam: cachedResult.isSpam
                });
                return cachedResult;
            }
            // Delegate to Rust bridge
            const bridge = RustSecurityBridge.getInstance();
            const rustResult = await bridge.checkIpReputation(ip);
            const result = {
                score: rustResult.score,
                isSpam: rustResult.listed_count > 0,
                isProxy: rustResult.ip_type === 'proxy',
                isTor: rustResult.ip_type === 'tor',
                isVPN: rustResult.ip_type === 'vpn',
                blacklists: rustResult.dnsbl_results
                    .filter(d => d.listed)
                    .map(d => d.server),
                timestamp: Date.now(),
            };
            this.reputationCache.set(ip, result);
            if (this.options.enableLocalCache) {
                this.saveCache().catch(error => {
                    logger.log('error', `Failed to save IP reputation cache: ${error.message}`);
                });
            }
            this.logReputationCheck(ip, result);
            return result;
        }
        catch (error) {
            logger.log('error', `Error checking IP reputation for ${ip}: ${error.message}`, {
                ip,
                stack: error.stack
            });
            return this.createErrorResult(ip, error.message);
        }
    }
    createErrorResult(ip, errorMessage) {
        return {
            score: 50,
            isSpam: false,
            isProxy: false,
            isTor: false,
            isVPN: false,
            timestamp: Date.now(),
            error: errorMessage
        };
    }
    isValidIPAddress(ip) {
        const ipv4Pattern = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
        return ipv4Pattern.test(ip);
    }
    logReputationCheck(ip, result) {
        let logLevel = SecurityLogLevel.INFO;
        if (result.score < this.options.highRiskThreshold) {
            logLevel = SecurityLogLevel.WARN;
        }
        SecurityLogger.getInstance().logEvent({
            level: logLevel,
            type: SecurityEventType.IP_REPUTATION,
            message: `IP reputation check ${result.isSpam ? 'flagged spam' : 'completed'} for ${ip}`,
            ipAddress: ip,
            details: {
                score: result.score,
                isSpam: result.isSpam,
                isProxy: result.isProxy,
                isTor: result.isTor,
                isVPN: result.isVPN,
                country: result.country,
                blacklists: result.blacklists
            },
            success: !result.isSpam
        });
    }
    async saveCache() {
        try {
            const entries = Array.from(this.reputationCache.entries()).map(([ip, data]) => ({
                ip,
                data
            }));
            if (entries.length === 0) {
                return;
            }
            const cacheData = JSON.stringify(entries);
            if (this.storageManager) {
                await this.storageManager.set('/security/ip-reputation-cache.json', cacheData);
                logger.log('info', `Saved ${entries.length} IP reputation cache entries to StorageManager`);
            }
            else {
                const cacheDir = plugins.path.join(paths.dataDir, 'security');
                await plugins.smartfs.directory(cacheDir).recursive().create();
                const cacheFile = plugins.path.join(cacheDir, 'ip_reputation_cache.json');
                await plugins.smartfs.file(cacheFile).write(cacheData);
                logger.log('info', `Saved ${entries.length} IP reputation cache entries to disk`);
            }
        }
        catch (error) {
            logger.log('error', `Failed to save IP reputation cache: ${error.message}`);
        }
    }
    async loadCache() {
        try {
            let cacheData = null;
            let fromFilesystem = false;
            if (this.storageManager) {
                try {
                    cacheData = await this.storageManager.get('/security/ip-reputation-cache.json');
                    if (!cacheData) {
                        const cacheFile = plugins.path.join(paths.dataDir, 'security', 'ip_reputation_cache.json');
                        if (plugins.fs.existsSync(cacheFile)) {
                            logger.log('info', 'Migrating IP reputation cache from filesystem to StorageManager');
                            cacheData = plugins.fs.readFileSync(cacheFile, 'utf8');
                            fromFilesystem = true;
                            await this.storageManager.set('/security/ip-reputation-cache.json', cacheData);
                            logger.log('info', 'IP reputation cache migrated to StorageManager successfully');
                            try {
                                plugins.fs.unlinkSync(cacheFile);
                                logger.log('info', 'Old cache file removed after migration');
                            }
                            catch (deleteError) {
                                logger.log('warn', `Could not delete old cache file: ${deleteError.message}`);
                            }
                        }
                    }
                }
                catch (error) {
                    logger.log('error', `Error loading from StorageManager: ${error.message}`);
                }
            }
            else {
                const cacheFile = plugins.path.join(paths.dataDir, 'security', 'ip_reputation_cache.json');
                if (plugins.fs.existsSync(cacheFile)) {
                    cacheData = plugins.fs.readFileSync(cacheFile, 'utf8');
                    fromFilesystem = true;
                }
            }
            if (cacheData) {
                const entries = JSON.parse(cacheData);
                const now = Date.now();
                const validEntries = entries.filter(entry => {
                    const age = now - entry.data.timestamp;
                    return age < this.options.cacheTTL;
                });
                for (const entry of validEntries) {
                    this.reputationCache.set(entry.ip, entry.data);
                }
                const source = fromFilesystem ? 'disk' : 'StorageManager';
                logger.log('info', `Loaded ${validEntries.length} IP reputation cache entries from ${source}`);
            }
        }
        catch (error) {
            logger.log('error', `Failed to load IP reputation cache: ${error.message}`);
        }
    }
    static getRiskLevel(score) {
        if (score < ReputationThreshold.HIGH_RISK) {
            return 'high';
        }
        else if (score < ReputationThreshold.MEDIUM_RISK) {
            return 'medium';
        }
        else if (score < ReputationThreshold.LOW_RISK) {
            return 'low';
        }
        else {
            return 'trusted';
        }
    }
    updateStorageManager(storageManager) {
        this.storageManager = storageManager;
        logger.log('info', 'IPReputationChecker storage manager updated');
        if (this.options.enableLocalCache && this.reputationCache.size > 0) {
            this.saveCache().catch(error => {
                logger.log('error', `Failed to save cache to new storage manager: ${error.message}`);
            });
        }
    }
}
//# sourceMappingURL=data:application/json;base64,[encoded data, 11360 characters]