import { readFile } from "node:fs/promises";
import { homedir } from "node:os";
import { join } from "node:path";
import { AsyncMutex } from "../utils/asyncMutex.js";
import { writeJsonSnapshotAtomically } from "./snapshotPersistence.js";
const COOLDOWN_FILE = "account-cooldowns.json";
const VALID_REASONS = new Set([
    "weekly",
    "session",
    "unified",
    "transient",
    "auth",
]);
let customCooldownFilePath = null;
let cacheLoaded = false;
let cacheLoadPromise = null;
let memoryCache = {};
const mutationMutex = new AsyncMutex();
export function initAccountCooldown(cooldownFilePath) {
    customCooldownFilePath = cooldownFilePath;
    cacheLoaded = false;
    cacheLoadPromise = null;
    memoryCache = {};
}
function getCooldownFilePath() {
    return customCooldownFilePath ?? join(homedir(), ".neurolink", COOLDOWN_FILE);
}
function isPersistedCooldown(value) {
    if (!value || typeof value !== "object") {
        return false;
    }
    const candidate = value;
    return (typeof candidate.coolingUntil === "number" &&
        Number.isFinite(candidate.coolingUntil) &&
        typeof candidate.updatedAt === "number" &&
        Number.isFinite(candidate.updatedAt) &&
        typeof candidate.reason === "string" &&
        VALID_REASONS.has(candidate.reason));
}
async function ensureAccountCooldownsLoaded() {
    if (!cacheLoaded) {
        if (!cacheLoadPromise) {
            cacheLoadPromise = (async () => {
                try {
                    const parsed = JSON.parse(await readFile(getCooldownFilePath(), "utf8"));
                    memoryCache = Object.fromEntries(Object.entries(parsed).filter((entry) => isPersistedCooldown(entry[1])));
                }
                catch {
                    memoryCache = {};
                }
                cacheLoaded = true;
            })().finally(() => {
                cacheLoadPromise = null;
            });
        }
        await cacheLoadPromise;
    }
}
export async function loadAccountCooldowns() {
    await ensureAccountCooldownsLoaded();
    return mutationMutex.runExclusive(async () => ({ ...memoryCache }));
}
export async function saveAccountCooldown(accountKey, coolingUntil, reason) {
    await mutationMutex.runExclusive(async () => {
        await ensureAccountCooldownsLoaded();
        const current = memoryCache[accountKey];
        if (current && current.coolingUntil > coolingUntil) {
            return;
        }
        memoryCache[accountKey] = {
            coolingUntil,
            reason,
            updatedAt: Date.now(),
        };
        await writeJsonSnapshotAtomically(getCooldownFilePath(), memoryCache);
    });
}
export async function clearAccountCooldown(accountKey, expectedCoolingUntil) {
    await mutationMutex.runExclusive(async () => {
        await ensureAccountCooldownsLoaded();
        const current = memoryCache[accountKey];
        if (!current) {
            return;
        }
        if (expectedCoolingUntil !== undefined &&
            current.coolingUntil !== expectedCoolingUntil) {
            return;
        }
        delete memoryCache[accountKey];
        await writeJsonSnapshotAtomically(getCooldownFilePath(), memoryCache);
    });
}
