'use strict';

/* ────────────────────────────────────────────────────────────────
   EPIC E9 — Monetization Tools
   
   In-app purchases, ad mediation, analytics, A/B testing,
   leaderboards, cloud saves
──────────────────────────────────────────────────────────────── */
function getActiveSubscriptions(store, now) {
    return store.purchaseHistory.filter(p => p.state === 'purchased' &&
        store.products.some(prod => prod.id === p.productId && prod.type === 'subscription') &&
        (!p.expiresAt || p.expiresAt > now));
}
function hasProduct(store, productId) {
    return store.purchaseHistory.some(p => p.productId === productId && p.state === 'purchased' && p.verified);
}
function getBalance(wallet, currencyId) {
    var _a;
    const entry = wallet.entries.find(e => e.currencyId === currencyId);
    return (_a = entry === null || entry === void 0 ? void 0 : entry.balance) !== null && _a !== void 0 ? _a : 0;
}
function modifyBalance(wallet, currencyId, amount, maxBalance = Infinity) {
    let entry = wallet.entries.find(e => e.currencyId === currencyId);
    if (!entry) {
        entry = { currencyId, balance: 0 };
        wallet.entries.push(entry);
    }
    const newBalance = entry.balance + amount;
    if (newBalance < 0)
        return false;
    entry.balance = Math.min(newBalance, maxBalance);
    return true;
}
class AnalyticsBuffer {
    constructor(config) {
        this.events = [];
        this.flushCallback = null;
        this.config = config;
    }
    onFlush(callback) {
        this.flushCallback = callback;
    }
    track(type, name, params = {}) {
        if (!this.config.enabled)
            return;
        if (this.config.sampleRate < 1 && Math.random() > this.config.sampleRate)
            return;
        this.events.push({
            type,
            name,
            timestamp: Date.now(),
            sessionId: '',
            params,
        });
        if (this.events.length >= this.config.batchSize) {
            this.flush();
        }
    }
    flush() {
        var _a;
        if (this.events.length === 0)
            return;
        const batch = this.events.splice(0);
        (_a = this.flushCallback) === null || _a === void 0 ? void 0 : _a.call(this, batch);
    }
    getBufferSize() {
        return this.events.length;
    }
}
/** Deterministic assignment based on userId hash. */
function assignVariant(test, userId) {
    let hash = 0;
    const key = test.id + userId;
    for (let i = 0; i < key.length; i++) {
        hash = ((hash << 5) - hash + key.charCodeAt(i)) | 0;
    }
    const normalized = Math.abs(hash) / 0x7FFFFFFF;
    let cumulative = 0;
    for (const variant of test.variants) {
        cumulative += variant.weight;
        if (normalized <= cumulative)
            return variant;
    }
    return test.variants[test.variants.length - 1];
}
function insertScore(entries, newEntry, sort, maxEntries) {
    const result = [...entries];
    result.push(newEntry);
    result.sort((a, b) => sort === 'highest' ? b.score - a.score : a.score - b.score);
    if (result.length > maxEntries)
        result.length = maxEntries;
    for (let i = 0; i < result.length; i++)
        result[i].rank = i + 1;
    return result;
}
function formatLeaderboardScore(score, format) {
    switch (format) {
        case 'integer': return Math.floor(score).toLocaleString();
        case 'decimal': return score.toFixed(2);
        case 'time': {
            const totalSec = Math.floor(score / 1000);
            const ms = score % 1000;
            const min = Math.floor(totalSec / 60);
            const sec = totalSec % 60;
            return `${min}:${sec.toString().padStart(2, '0')}.${ms.toString().padStart(3, '0')}`;
        }
        default: return String(score);
    }
}
/** Simple checksum for save integrity. */
function computeChecksum(data) {
    let hash = 0;
    for (let i = 0; i < data.length; i++) {
        hash = ((hash << 5) - hash + data.charCodeAt(i)) | 0;
    }
    return (hash >>> 0).toString(16).padStart(8, '0');
}
class AchievementTracker {
    constructor() {
        this.definitions = new Map();
        this.progress = new Map();
    }
    registerAchievement(def) {
        this.definitions.set(def.id, def);
        if (!this.progress.has(def.id)) {
            this.progress.set(def.id, { achievementId: def.id, unlocked: false, progress: 0 });
        }
    }
    incrementProgress(achievementId, amount = 1) {
        var _a, _b;
        const def = this.definitions.get(achievementId);
        const prog = this.progress.get(achievementId);
        if (!def || !prog || prog.unlocked)
            return false;
        prog.progress = Math.min(prog.progress + amount, (_a = def.maxProgress) !== null && _a !== void 0 ? _a : 1);
        if (prog.progress >= ((_b = def.maxProgress) !== null && _b !== void 0 ? _b : 1)) {
            prog.unlocked = true;
            prog.unlockedAt = Date.now();
            return true; // Newly unlocked
        }
        return false;
    }
    unlock(achievementId) {
        var _a;
        const prog = this.progress.get(achievementId);
        if (!prog || prog.unlocked)
            return false;
        const def = this.definitions.get(achievementId);
        if (!def)
            return false;
        prog.unlocked = true;
        prog.progress = (_a = def.maxProgress) !== null && _a !== void 0 ? _a : 1;
        prog.unlockedAt = Date.now();
        return true;
    }
    isUnlocked(achievementId) {
        var _a, _b;
        return (_b = (_a = this.progress.get(achievementId)) === null || _a === void 0 ? void 0 : _a.unlocked) !== null && _b !== void 0 ? _b : false;
    }
    getProgress(achievementId) {
        return this.progress.get(achievementId);
    }
    getUnlockedCount() {
        let count = 0;
        this.progress.forEach(p => { if (p.unlocked)
            count++; });
        return count;
    }
    getTotalPoints() {
        let total = 0;
        this.progress.forEach((p, id) => {
            if (p.unlocked) {
                const def = this.definitions.get(id);
                if (def)
                    total += def.points;
            }
        });
        return total;
    }
    getAllProgress() {
        const result = [];
        this.progress.forEach(p => result.push(p));
        return result;
    }
}

exports.AchievementTracker = AchievementTracker;
exports.AnalyticsBuffer = AnalyticsBuffer;
exports.assignVariant = assignVariant;
exports.computeChecksum = computeChecksum;
exports.formatLeaderboardScore = formatLeaderboardScore;
exports.getActiveSubscriptions = getActiveSubscriptions;
exports.getBalance = getBalance;
exports.hasProduct = hasProduct;
exports.insertScore = insertScore;
exports.modifyBalance = modifyBalance;
//# sourceMappingURL=Monetization.js.map
