import { openDB } from 'idb';
export var TTL;
(function (TTL) {
    TTL[TTL["OneMinute"] = 60000] = "OneMinute";
    TTL[TTL["FiveMinutes"] = 300000] = "FiveMinutes";
    TTL[TTL["OneHour"] = 3600000] = "OneHour";
    TTL[TTL["OneDay"] = 86400000] = "OneDay";
    TTL[TTL["OneWeek"] = 604800000] = "OneWeek";
    TTL[TTL["OneMonth"] = 2592000000] = "OneMonth";
})(TTL || (TTL = {}));
export class Cache {
    db = null;
    dbName;
    dbVersion;
    constructor() {
        this.dbName = 'app-cache';
        this.dbVersion = 1;
    }
    /**
     * Initialize the database connection
     */
    async database() {
        if (this.db) {
            return this.db;
        }
        try {
            this.db = await openDB(this.dbName, this.dbVersion, {
                upgrade(db) {
                    if (!db.objectStoreNames.contains('cache')) {
                        db.createObjectStore('cache');
                    }
                },
            });
            return this.db;
        }
        catch {
            throw new Error('Cache initialization failed');
        }
    }
    /**
     * Store data in the cache with optional TTL
     *
     * @param key - The key to store the data under
     * @param data - The data to store
     * @param ttl - Time to live in milliseconds
     * @returns A promise that resolves to true if the data was stored successfully, false otherwise
     */
    async set(key, data, ttl) {
        try {
            const db = await this.database();
            const now = Date.now();
            const expiresAt = ttl ? now + ttl : Number.MAX_SAFE_INTEGER;
            const item = {
                data,
                expiresAt,
                createdAt: now,
            };
            await db.put('cache', item, key);
            return true;
        }
        catch {
            return false;
        }
    }
    /**
     * Retrieve data from the cache with type safety
     */
    async get(key) {
        try {
            const db = await this.database();
            const item = await db.get('cache', key);
            if (!item) {
                return null;
            }
            const now = Date.now();
            // Check if item has expired
            if (now > item.expiresAt) {
                // Clean up expired item
                await this.delete(key);
                return null;
            }
            return item.data;
        }
        catch {
            return null;
        }
    }
    /**
     * Check if a key exists and is not expired
     */
    async has(key) {
        try {
            const db = await this.database();
            const item = await db.get('cache', key);
            if (!item) {
                return false;
            }
            const now = Date.now();
            if (now > item.expiresAt) {
                // Clean up expired item
                await this.delete(key);
                return false;
            }
            return true;
        }
        catch {
            return false;
        }
    }
    /**
     * Delete a specific cache item
     */
    async delete(key) {
        try {
            const db = await this.database();
            await db.delete('cache', key);
            return true;
        }
        catch {
            return false;
        }
    }
    /**
     * Clear all cache items
     */
    async clear() {
        try {
            const db = await this.database();
            await db.clear('cache');
            return true;
        }
        catch {
            return false;
        }
    }
    /**
     * Get cache statistics
     */
    async stats() {
        try {
            const db = await this.database();
            const allKeys = await db.getAllKeys('cache');
            const now = Date.now();
            let expiredItems = 0;
            let validItems = 0;
            for (const key of allKeys) {
                const item = await db.get('cache', key);
                if (item) {
                    if (now > item.expiresAt) {
                        expiredItems++;
                    }
                    else {
                        validItems++;
                    }
                }
            }
            return {
                totalItems: allKeys.length,
                expiredItems,
                validItems,
            };
        }
        catch {
            return null;
        }
    }
    /**
     * Clean up expired items
     */
    async cleanup() {
        try {
            const db = await this.database();
            const allKeys = await db.getAllKeys('cache');
            const now = Date.now();
            let cleanedCount = 0;
            for (const key of allKeys) {
                const item = await db.get('cache', key);
                if (item && now > item.expiresAt) {
                    await db.delete('cache', key);
                    cleanedCount++;
                }
            }
            return cleanedCount;
        }
        catch {
            return 0;
        }
    }
    /**
     * Get multiple cache items at once
     */
    async getMany(keys) {
        const results = [];
        for (const key of keys) {
            const value = await this.get(key);
            results.push(value);
        }
        return results;
    }
    /**
     * Set multiple cache items at once
     */
    async setMany(items) {
        const results = [];
        for (const item of items) {
            const success = await this.set(item.key, item.data, item.ttl);
            results.push(success);
        }
        return results;
    }
    /**
     * Close the database connection
     */
    async close() {
        if (this.db) {
            this.db.close();
            this.db = null;
        }
    }
}
//# sourceMappingURL=Cache.js.map