export class ContextManager {
    constructor() {
        this.keepToolOutputTurns = 5; 
        this.tokenLimit = 100000; 
        this.rules = this.loadRules();
        this.worldInfo = [];
        this.activeWorldInfoCache = new Map();
        this.cacheDuration = 3; 
    }

    loadRules() {
        try {
            const savedRules = localStorage.getItem('amily2_acc_rules');
            if (savedRules) {
                return JSON.parse(savedRules);
            }
        } catch (e) {
            console.error('[AutoCharCard] Failed to load rules:', e);
        }
        return [];
    }

    saveRules() {
        try {
            localStorage.setItem('amily2_acc_rules', JSON.stringify(this.rules));
        } catch (e) {
            console.error('[AutoCharCard] Failed to save rules:', e);
        }
    }

    addRule(rule) {
        this.rules.push({
            id: rule.id || Date.now().toString(),
            keyword: rule.keyword || null, 
            content: rule.content,
            enabled: rule.enabled !== undefined ? rule.enabled : true
        });
        this.saveRules();
    }

    removeRule(index) {
        if (index >= 0 && index < this.rules.length) {
            this.rules.splice(index, 1);
            this.saveRules();
        }
    }

    setWorldInfo(entries) {
        this.worldInfo = entries.map(entry => {
            let keys = [];
            if (Array.isArray(entry.key)) {
                keys = entry.key;
            } else if (typeof entry.key === 'string') {
                keys = entry.key.split(',').map(k => k.trim()).filter(k => k);
            }
            
            return {
                id: entry.uid,
                keys: keys,
                content: entry.content,
                enabled: entry.enabled !== false
            };
        });
    }

    getRelevantContext(contextText) {
        const relevantRules = this.rules.filter(rule => {
            if (!rule.enabled) return false;
            if (!rule.keyword) return true; 
            return contextText.includes(rule.keyword);
        });

        const currentMatches = this.worldInfo.filter(entry => {
            if (!entry.enabled) return false;
            if (!entry.keys || entry.keys.length === 0) return false;
            return entry.keys.some(key => contextText.includes(key));
        });

        for (const [uid, data] of this.activeWorldInfoCache) {
            data.turnsLeft--;
            if (data.turnsLeft <= 0) {
                this.activeWorldInfoCache.delete(uid);
            }
        }

        currentMatches.forEach(entry => {
            this.activeWorldInfoCache.set(entry.id, { turnsLeft: this.cacheDuration });
        });

        const allRelevantUIDs = new Set([...currentMatches.map(e => e.id), ...this.activeWorldInfoCache.keys()]);
        
        const relevantWorldInfo = this.worldInfo.filter(entry => allRelevantUIDs.has(entry.id));

        return {
            rules: relevantRules,
            worldInfo: relevantWorldInfo
        };
    }

    estimateTokens(text) {
        return Math.ceil((text || '').length / 3.5);
    }

    buildMessages(systemPrompt, history, maxTokens) {
        const limit = maxTokens || this.tokenLimit;
        const systemTokens = this.estimateTokens(systemPrompt);
        let availableTokens = limit - systemTokens - 1000; 

        if (availableTokens < 0) availableTokens = 1000; 

        const optimizedHistory = this.optimizeToolOutputs(history);

        const finalMessages = [];
        let currentTokens = 0;

        for (let i = optimizedHistory.length - 1; i >= 0; i--) {
            const msg = optimizedHistory[i];
            const msgTokens = this.estimateTokens(msg.content);

            if (currentTokens + msgTokens > availableTokens) {
                finalMessages.unshift({ role: 'system', content: "[Earlier history truncated to save tokens]" });
                break;
            }

            finalMessages.unshift(msg);
            currentTokens += msgTokens;
        }

        return [
            { role: 'system', content: systemPrompt },
            ...finalMessages
        ];
    }

    optimizeToolOutputs(history) {
        let toolOutputCount = 0;
        const reversedHistory = [...history].reverse();
        
        const processedReversed = reversedHistory.map((msg) => {
            if (msg.role === 'user' && msg.content.startsWith('[Tool Result')) {
                toolOutputCount++;
                
                if (toolOutputCount > this.keepToolOutputTurns) {
                    const firstLine = msg.content.split('\n')[0];
                    return {
                        role: msg.role,
                        content: `${firstLine}\n[Content hidden to save tokens. The tool was executed successfully.]`
                    };
                }
            }
            return msg;
        });

        return processedReversed.reverse();
    }
}
