"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutcomeEngine = void 0;
const TREND_WINDOW = 10;
const DEAD_DAYS = 30;
const MIN_RELIABLE = 5;
class OutcomeEngine {
    store;
    constructor(store) {
        this.store = store;
    }
    recordEvent(event) {
        this.store.addEvent(event);
        const summary = this.computeSummary(event.patternId);
        this.store.addSummary(summary);
        return summary;
    }
    getSummary(patternId) {
        let summary = this.store.getSummary(patternId);
        if (!summary) {
            const events = this.store.getEvents(patternId);
            if (events.length > 0) {
                summary = this.computeSummary(patternId);
                this.store.addSummary(summary);
            }
        }
        return summary;
    }
    getAllSummaries() {
        return this.store.getAllSummaries();
    }
    getEventCount() {
        return this.store.getEventCount();
    }
    generateLeaderboard() {
        const summaries = this.store.getAllSummaries();
        const now = Date.now();
        return {
            mostSuccessful: this.rank(summaries, 'successCount', 'desc', 10),
            mostReliable: this.rankFiltered(summaries, 'successRate', 'desc', 10, MIN_RELIABLE),
            mostAccepted: this.rankFiltered(summaries, 'acceptanceRate', 'desc', 10, MIN_RELIABLE),
            fastestGrowing: this.rankFastestGrowing(summaries, now),
            mostFailed: this.rank(summaries, 'failureCount', 'desc', 10),
            mostRejected: this.rank(summaries, 'rejectionCount', 'desc', 10),
            generatedAt: now,
        };
    }
    computeSummary(patternId) {
        const events = this.store.getEvents(patternId);
        const now = Date.now();
        let usageCount = 0;
        let successCount = 0;
        let failureCount = 0;
        let acceptanceCount = 0;
        let rejectionCount = 0;
        let lastOutcome = null;
        let lastSuccessTimestamp = null;
        let lastFailureTimestamp = null;
        let firstSeen = now;
        let lastSeen = 0;
        for (const evt of events) {
            if (evt.timestamp < firstSeen)
                firstSeen = evt.timestamp;
            if (evt.timestamp > lastSeen)
                lastSeen = evt.timestamp;
            lastOutcome = evt.type;
            switch (evt.type) {
                case 'PATTERN_USED':
                    usageCount++;
                    break;
                case 'PATTERN_SUCCESS':
                    successCount++;
                    usageCount++;
                    lastSuccessTimestamp = evt.timestamp;
                    break;
                case 'PATTERN_FAILURE':
                    failureCount++;
                    usageCount++;
                    lastFailureTimestamp = evt.timestamp;
                    break;
                case 'PATTERN_ACCEPTED':
                    acceptanceCount++;
                    usageCount++;
                    break;
                case 'PATTERN_REJECTED':
                    rejectionCount++;
                    usageCount++;
                    break;
                case 'PATTERN_MODIFIED':
                    usageCount++;
                    break;
                case 'PATTERN_REPLACED':
                    usageCount++;
                    break;
            }
        }
        const totalAccepted = acceptanceCount + successCount;
        const totalRejected = rejectionCount + failureCount;
        const totalOutcomes = totalAccepted + totalRejected;
        const successRate = usageCount > 0 ? successCount / usageCount : 0;
        const failureRate = usageCount > 0 ? failureCount / usageCount : 0;
        const acceptanceRate = totalOutcomes > 0 ? totalAccepted / totalOutcomes : 0;
        const confidence = this.computeConfidence(successCount, failureCount, acceptanceCount, rejectionCount, usageCount);
        const trend = this.computeTrend(events, successCount, failureCount, usageCount, now);
        const health = this.computeHealth(successRate, confidence, usageCount, trend, lastSeen, now);
        const summary = {
            patternId,
            usageCount,
            successCount,
            failureCount,
            acceptanceCount,
            rejectionCount,
            lastOutcome,
            lastSuccessTimestamp,
            lastFailureTimestamp,
            successRate,
            failureRate,
            acceptanceRate,
            confidence,
            trend,
            health,
            firstSeen,
            lastSeen,
        };
        return summary;
    }
    computeConfidence(successCount, failureCount, acceptanceCount, rejectionCount, usageCount) {
        if (usageCount === 0)
            return 0.5;
        const evidenceScore = (successCount + acceptanceCount * 0.5) / Math.max(usageCount, 1);
        const bayesian = (evidenceScore * usageCount + 0.5 * 3) / (usageCount + 3);
        return Math.round(bayesian * 1000) / 1000;
    }
    computeTrend(events, totalSuccess, totalFailure, totalUsage, now) {
        const recent = events.slice(-TREND_WINDOW);
        const recentSuccess = recent.filter(e => e.type === 'PATTERN_SUCCESS' || e.type === 'PATTERN_ACCEPTED').length;
        const recentFailure = recent.filter(e => e.type === 'PATTERN_FAILURE' || e.type === 'PATTERN_REJECTED').length;
        const recentTotal = recentSuccess + recentFailure;
        const recentRate = recentTotal > 0 ? recentSuccess / recentTotal : 0;
        if (events.length === 0)
            return 'dead';
        const newest = events[events.length - 1];
        const daysSinceLast = (now - newest.timestamp) / (1000 * 60 * 60 * 24);
        if (daysSinceLast > DEAD_DAYS)
            return 'dead';
        if (recentTotal < 2)
            return 'stable';
        const overallRate = totalUsage > 0 ? totalSuccess / totalUsage : 0;
        if (recentRate > overallRate + 0.1)
            return 'rising';
        if (recentRate < overallRate - 0.1)
            return 'declining';
        return 'stable';
    }
    computeHealth(successRate, confidence, usageCount, trend, lastSeen, now) {
        const trendScore = { rising: 1, stable: 0.6, declining: 0.3, dead: 0 };
        const usageVolume = Math.min(usageCount / 100, 1);
        const daysSinceLast = (now - lastSeen) / (1000 * 60 * 60 * 24);
        const recencyScore = Math.max(0, 1 - daysSinceLast / DEAD_DAYS);
        const raw = successRate * 30 +
            confidence * 25 +
            usageVolume * 20 +
            trendScore[trend] * 15 +
            recencyScore * 10;
        return Math.round(Math.min(raw, 100));
    }
    rank(summaries, field, order, limit) {
        const sorted = [...summaries]
            .filter(s => typeof s[field] === 'number')
            .sort((a, b) => {
            const va = a[field];
            const vb = b[field];
            return order === 'desc' ? vb - va : va - vb;
        });
        return sorted.slice(0, limit).map((s, i) => ({
            patternId: s.patternId,
            score: s[field],
            rank: i + 1,
            metrics: {
                usageCount: s.usageCount,
                successRate: s.successRate,
                acceptanceRate: s.acceptanceRate,
                confidence: s.confidence,
                health: s.health,
            },
        }));
    }
    rankFiltered(summaries, field, order, limit, minUsage) {
        return this.rank(summaries.filter(s => s.usageCount >= minUsage), field, order, limit);
    }
    rankFastestGrowing(summaries, _now) {
        const order = ['rising', 'stable', 'declining', 'dead'];
        const sorted = [...summaries].sort((a, b) => {
            const ta = order.indexOf(a.trend);
            const tb = order.indexOf(b.trend);
            if (ta !== tb)
                return ta - tb;
            return (b.confidence - a.confidence);
        });
        return sorted.slice(0, 10).map((s, i) => ({
            patternId: s.patternId,
            score: order.indexOf(s.trend) === 0 ? 100 - i : 50 - i,
            rank: i + 1,
            metrics: {
                trend: order.indexOf(s.trend),
                confidence: s.confidence,
                health: s.health,
                usageCount: s.usageCount,
            },
        }));
    }
    save() {
        this.store.save();
    }
    getStore() {
        return this.store;
    }
}
exports.OutcomeEngine = OutcomeEngine;
//# sourceMappingURL=outcome-engine.js.map