/** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
import { randomUUID } from 'node:crypto';
import { mkdirSync } from 'node:fs';
import { rename } from 'node:fs/promises';
import { join } from 'node:path';
const MAX_HISTORY = 100;
function emptyData() {
    return { pinned: [], history: [] };
}
export class FavoritesStore {
    dir;
    cache = null;
    constructor(options) {
        this.dir = options.dir;
    }
    getDirectory() {
        return this.dir;
    }
    getPath() {
        return join(this.dir, 'favorites.json');
    }
    async load() {
        const file = Bun.file(this.getPath());
        if (!await file.exists()) {
            const empty = emptyData();
            this.cache = empty;
            return empty;
        }
        try {
            const text = await file.text();
            const parsed = JSON.parse(text);
            const loaded = {
                pinned: Array.isArray(parsed.pinned) ? parsed.pinned : [],
                history: Array.isArray(parsed.history) ? parsed.history : [],
            };
            this.cache = loaded;
            return loaded;
        }
        catch {
            const empty = emptyData();
            this.cache = empty;
            return empty;
        }
    }
    async save(data) {
        mkdirSync(this.dir, { recursive: true });
        const path = this.getPath();
        const tmp = `${path}.tmp.${randomUUID()}`;
        await Bun.write(tmp, JSON.stringify(data, null, 2));
        await rename(tmp, path);
        this.cache = data;
    }
    async pinModel(id) {
        const data = await this.getData();
        if (data.pinned.some((entry) => entry.modelId === id))
            return;
        data.pinned.push({ modelId: id, pinnedAt: new Date().toISOString() });
        await this.save(data);
    }
    async unpinModel(id) {
        const data = await this.getData();
        data.pinned = data.pinned.filter((entry) => entry.modelId !== id);
        await this.save(data);
    }
    async getPinned() {
        const data = await this.getData();
        return data.pinned.map((entry) => entry.modelId);
    }
    async isModelPinned(id) {
        const data = await this.getData();
        return data.pinned.some((entry) => entry.modelId === id);
    }
    async recordUsage(id) {
        const data = await this.getData();
        const now = new Date().toISOString();
        const existing = data.history.find((entry) => entry.modelId === id);
        if (existing) {
            existing.count += 1;
            existing.lastUsed = now;
        }
        else {
            data.history.push({ modelId: id, lastUsed: now, count: 1 });
        }
        if (data.history.length > MAX_HISTORY) {
            data.history.sort((a, b) => a.lastUsed.localeCompare(b.lastUsed));
            data.history = data.history.slice(data.history.length - MAX_HISTORY);
        }
        await this.save(data);
    }
    async getRecentModels(n) {
        const data = await this.getData();
        return data.history
            .slice()
            .sort((a, b) => b.lastUsed.localeCompare(a.lastUsed))
            .slice(0, n)
            .map((entry) => entry.modelId);
    }
    async getData() {
        if (this.cache)
            return this.cache;
        return this.load();
    }
}
