import { createDocumentStore } from "./state-backend.js";
export class BotPreferencesStore {
    store;
    contexts = new Map();
    constructor(workspace, backend = "json") {
        this.store = createDocumentStore({
            workspace,
            fileName: "preferences.json",
            sqliteKey: "preferences",
            backend,
        });
        this.load();
    }
    get(contextKey) {
        this.load();
        return { ...(this.contexts.get(contextKey) ?? {}) };
    }
    list() {
        this.load();
        return [...this.contexts.entries()].map(([contextKey, preferences]) => ({
            contextKey,
            preferences: { ...preferences },
        }));
    }
    update(contextKey, patch) {
        let updated = {};
        const payload = this.store.update((current) => {
            const payload = normalizePayload(current);
            const previous = payload.contexts[contextKey] ?? {};
            updated = pruneEmptyPreferences({
                ...previous,
                ...patch,
            });
            payload.contexts[contextKey] = updated;
            return payload;
        });
        this.replaceContexts(payload);
        return { ...updated };
    }
    clear(contextKey) {
        const payload = this.store.update((current) => {
            const payload = normalizePayload(current);
            delete payload.contexts[contextKey];
            return payload;
        });
        this.replaceContexts(payload);
    }
    load() {
        this.replaceContexts(normalizePayload(this.store.read()));
    }
    replaceContexts(payload) {
        this.contexts.clear();
        for (const [contextKey, rawPreferences] of Object.entries(payload.contexts)) {
            const preferences = normalizePreferences(rawPreferences);
            if (preferences) {
                this.contexts.set(contextKey, preferences);
            }
        }
    }
}
function normalizePayload(payload) {
    if (!payload?.contexts || typeof payload.contexts !== "object") {
        return { version: 1, contexts: {} };
    }
    return {
        version: 1,
        contexts: Object.fromEntries(Object.entries(payload.contexts)
            .map(([contextKey, preferences]) => [contextKey, normalizePreferences(preferences)])
            .filter((entry) => Boolean(entry[1]))),
    };
}
export function parseMirrorMode(value, fallback) {
    const normalized = value?.trim().toLowerCase();
    if (normalized === "off" || normalized === "status" || normalized === "final" || normalized === "full") {
        return normalized;
    }
    return fallback;
}
export function parseNotifyMode(value, fallback) {
    const normalized = value?.trim().toLowerCase();
    if (normalized === "off" || normalized === "minimal" || normalized === "all") {
        return normalized;
    }
    return fallback;
}
export function parseVoiceBackendPreference(value) {
    const normalized = value?.trim().toLowerCase();
    if (normalized === "parakeet" ||
        normalized === "faster-whisper" ||
        normalized === "cohere-transcribe" ||
        normalized === "openai") {
        return normalized;
    }
    return "auto";
}
export function parseQuietHours(value) {
    if (!value) {
        return null;
    }
    const match = value.trim().match(/^(\d{1,2})\s*-\s*(\d{1,2})$/);
    if (!match) {
        throw new Error("Quiet hours must use HH-HH format, e.g. 22-7");
    }
    const startHour = Number(match[1]);
    const endHour = Number(match[2]);
    if (!Number.isInteger(startHour) || !Number.isInteger(endHour) || startHour < 0 || startHour > 23 || endHour < 0 || endHour > 23) {
        throw new Error("Quiet hours must use hours from 0 to 23");
    }
    return { startHour, endHour };
}
export function isQuietNow(quietHours, now = new Date()) {
    if (!quietHours) {
        return false;
    }
    const hour = now.getHours();
    if (quietHours.startHour === quietHours.endHour) {
        return true;
    }
    if (quietHours.startHour < quietHours.endHour) {
        return hour >= quietHours.startHour && hour < quietHours.endHour;
    }
    return hour >= quietHours.startHour || hour < quietHours.endHour;
}
export function formatQuietHours(quietHours) {
    if (!quietHours) {
        return "off";
    }
    return `${quietHours.startHour.toString().padStart(2, "0")}-${quietHours.endHour.toString().padStart(2, "0")}`;
}
function normalizePreferences(value) {
    if (!value || typeof value !== "object" || Array.isArray(value)) {
        return null;
    }
    const candidate = value;
    return pruneEmptyPreferences({
        mirrorMode: isMirrorMode(candidate.mirrorMode) ? candidate.mirrorMode : undefined,
        notifyMode: isNotifyMode(candidate.notifyMode) ? candidate.notifyMode : undefined,
        quietHours: normalizeQuietHours(candidate.quietHours),
        voiceBackend: isVoiceBackendPreference(candidate.voiceBackend) ? candidate.voiceBackend : undefined,
        voiceLanguage: typeof candidate.voiceLanguage === "string" ? candidate.voiceLanguage : candidate.voiceLanguage === null ? null : undefined,
        voiceTranscribeOnly: typeof candidate.voiceTranscribeOnly === "boolean" ? candidate.voiceTranscribeOnly : undefined,
        targetPeerId: typeof candidate.targetPeerId === "string" ? candidate.targetPeerId : candidate.targetPeerId === null ? null : undefined,
        targetThreadId: typeof candidate.targetThreadId === "string" ? candidate.targetThreadId : candidate.targetThreadId === null ? null : undefined,
        targetAgentId: typeof candidate.targetAgentId === "string" ? candidate.targetAgentId : candidate.targetAgentId === null ? null : undefined,
    });
}
function pruneEmptyPreferences(preferences) {
    return Object.fromEntries(Object.entries(preferences).filter(([, value]) => value !== undefined));
}
function normalizeQuietHours(value) {
    if (value === null) {
        return null;
    }
    if (!value || typeof value !== "object" || Array.isArray(value)) {
        return undefined;
    }
    const candidate = value;
    return Number.isInteger(candidate.startHour) &&
        Number.isInteger(candidate.endHour) &&
        candidate.startHour >= 0 &&
        candidate.startHour <= 23 &&
        candidate.endHour >= 0 &&
        candidate.endHour <= 23
        ? { startHour: candidate.startHour, endHour: candidate.endHour }
        : undefined;
}
function isMirrorMode(value) {
    return value === "off" || value === "status" || value === "final" || value === "full";
}
function isNotifyMode(value) {
    return value === "off" || value === "minimal" || value === "all";
}
function isVoiceBackendPreference(value) {
    return value === "auto" || value === "parakeet" || value === "faster-whisper" || value === "cohere-transcribe" || value === "openai";
}
