"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommunityLive = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const community_prior_1 = require("./community-prior");
class CommunityLive {
    prior;
    statsPath;
    optOutPath;
    constructor(cellDir) {
        this.prior = new community_prior_1.CommunityPrior(cellDir);
        this.statsPath = path.join(cellDir, 'community', 'live-stats.json');
        this.optOutPath = path.join(cellDir, 'community', 'opt-out.json');
    }
    ingestSignals(signals) {
        let ingested = 0;
        let replaced = 0;
        for (const signal of signals) {
            const existing = this.prior.getPatterns().find(p => p.patternId === signal.patternId);
            if (!existing)
                continue;
            const cpEntry = this.prior.getCommunityPattern(signal.patternId);
            if (!cpEntry)
                continue;
            if (cpEntry.isSynthetic) {
                const livePattern = this.createLivePattern(cpEntry.pattern, signal.positive, signal.negative);
                this.prior.replaceSyntheticWithLive(signal.patternId, livePattern);
                replaced++;
            }
            else {
                cpEntry.pattern.signals.positive += signal.positive;
                cpEntry.pattern.signals.negative += signal.negative;
                cpEntry.pattern.signals.total += signal.positive + signal.negative;
                cpEntry.sourceCount += signal.sourceCount;
            }
            ingested++;
        }
        this.prior.save();
        const stats = this.computeStats(ingested, replaced);
        this.saveStats(stats);
        return stats;
    }
    getDisplayLabel() {
        const liveCount = this.prior.getLivePatterns().length;
        const syntheticCount = this.prior.getSyntheticPatterns().length;
        if (liveCount >= 1000) {
            return `Community patterns (learned from ${this.formatNumber(liveCount)}+ developers)`;
        }
        if (liveCount > 0 && syntheticCount > 0) {
            return `Community patterns (${liveCount} live + ${syntheticCount} synthetic, improving with real data)`;
        }
        if (liveCount > 0) {
            return `Community patterns (learned from ${liveCount} developers)`;
        }
        return 'Community patterns (synthetic seed, improving with real data)';
    }
    applyFasterDecay() {
        const syntheticPatterns = this.prior.getSyntheticPatterns();
        for (const pattern of syntheticPatterns) {
            pattern.confidence.mean = Math.max(0.3, pattern.confidence.mean * 0.95);
            pattern.confidence.ci95 = [
                Math.max(0.2, pattern.confidence.ci95[0] * 0.95),
                Math.min(0.8, pattern.confidence.ci95[1] * 0.95),
            ];
        }
        this.prior.save();
    }
    isOptedOut(username) {
        if (!fs.existsSync(this.optOutPath))
            return false;
        try {
            const optOuts = JSON.parse(fs.readFileSync(this.optOutPath, 'utf-8'));
            return optOuts.includes(username);
        }
        catch {
            return false;
        }
    }
    optOut(username) {
        const optOuts = fs.existsSync(this.optOutPath)
            ? JSON.parse(fs.readFileSync(this.optOutPath, 'utf-8'))
            : [];
        if (!optOuts.includes(username)) {
            optOuts.push(username);
            fs.writeFileSync(this.optOutPath, JSON.stringify(optOuts, null, 2), 'utf-8');
        }
    }
    optIn(username) {
        if (!fs.existsSync(this.optOutPath))
            return;
        const optOuts = JSON.parse(fs.readFileSync(this.optOutPath, 'utf-8'));
        const idx = optOuts.indexOf(username);
        if (idx >= 0) {
            optOuts.splice(idx, 1);
            fs.writeFileSync(this.optOutPath, JSON.stringify(optOuts, null, 2), 'utf-8');
        }
    }
    getStats() {
        if (!fs.existsSync(this.statsPath)) {
            return { totalIngested: 0, syntheticReplaced: 0, remainingSynthetic: this.prior.getSyntheticPatterns().length, lastIngestion: '', trackingStart: '', weeklyRate: 0 };
        }
        try {
            return JSON.parse(fs.readFileSync(this.statsPath, 'utf-8'));
        }
        catch {
            return { totalIngested: 0, syntheticReplaced: 0, remainingSynthetic: this.prior.getSyntheticPatterns().length, lastIngestion: '', trackingStart: '', weeklyRate: 0 };
        }
    }
    createLivePattern(synthetic, positive, negative) {
        return {
            ...synthetic,
            signals: { positive, negative, total: positive + negative, lastSignal: Date.now() },
            attribution: {
                primaryCondition: 'live_learned',
                conditionConfidence: 0.9,
                sourceFiles: [],
                note: 'Learned from real developer data',
            },
        };
    }
    computeStats(ingested, replaced) {
        const existing = this.getStats();
        const now = new Date().toISOString();
        return {
            totalIngested: existing.totalIngested + ingested,
            syntheticReplaced: existing.syntheticReplaced + replaced,
            remainingSynthetic: this.prior.getSyntheticPatterns().length,
            lastIngestion: now,
            trackingStart: existing.trackingStart || now,
            weeklyRate: Math.round((existing.totalIngested + ingested) / Math.max(1, this.getWeeksSinceStart())),
        };
    }
    getWeeksSinceStart() {
        const stats = this.getStats();
        const startDate = stats.trackingStart || stats.lastIngestion;
        if (!startDate)
            return 1;
        const days = (Date.now() - new Date(startDate).getTime()) / 86400000;
        return Math.max(1, Math.ceil(Math.max(days, 1) / 7));
    }
    saveStats(stats) {
        const dir = path.dirname(this.statsPath);
        if (!fs.existsSync(dir))
            fs.mkdirSync(dir, { recursive: true });
        fs.writeFileSync(this.statsPath, JSON.stringify(stats, null, 2), 'utf-8');
    }
    formatNumber(n) {
        if (n >= 10000)
            return `${Math.floor(n / 1000)}K`;
        if (n >= 1000)
            return `${(n / 1000).toFixed(1)}K`;
        return String(n);
    }
}
exports.CommunityLive = CommunityLive;
//# sourceMappingURL=community-live.js.map