import { createHash, randomUUID } from "node:crypto";
import { AsyncEntry } from "@napi-rs/keyring";
import { keyFor, maskSecret } from "./SecureStore.js";
const DEFAULT_SERVICE = "patchtrail.agent-bridge.credentials";
export class OsKeyringSecureStore {
    service;
    entryFactory;
    constructor(service = DEFAULT_SERVICE, entryFactory = (serviceName, account) => new AsyncEntry(serviceName, account)) {
        this.service = service;
        this.entryFactory = entryFactory;
    }
    async get(ref) {
        const raw = await this.entryFor(ref).getPassword();
        if (!raw)
            return undefined;
        return parseEnvelope(raw).secret;
    }
    async set(ref, secret) {
        await this.entryFor(ref).setPassword(JSON.stringify({
            version: 1,
            secret,
            updatedAt: new Date().toISOString(),
            credentialVersion: randomUUID(),
        }));
    }
    async delete(ref) {
        await this.entryFor(ref).deleteCredential();
    }
    async status(ref) {
        const raw = await this.entryFor(ref).getPassword();
        if (!raw)
            return { ref, state: "missing", backend: "os_keyring" };
        const envelope = parseEnvelope(raw);
        const status = {
            ref,
            state: "available",
            maskedLabel: maskSecret(envelope.secret),
            backend: "os_keyring",
        };
        if (envelope.updatedAt)
            status.updatedAt = envelope.updatedAt;
        if (envelope.credentialVersion) {
            status.credentialVersion = envelope.credentialVersion;
        }
        return status;
    }
    entryFor(ref) {
        return this.entryFactory(this.service, accountFor(ref));
    }
}
function accountFor(ref) {
    return createHash("sha256").update(keyFor(ref)).digest("hex");
}
function parseEnvelope(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (typeof parsed === "object" &&
            parsed !== null &&
            "secret" in parsed &&
            typeof parsed.secret === "string") {
            const updatedAt = "updatedAt" in parsed && typeof parsed.updatedAt === "string"
                ? parsed.updatedAt
                : undefined;
            const credentialVersion = "credentialVersion" in parsed &&
                typeof parsed.credentialVersion === "string"
                ? parsed.credentialVersion
                : undefined;
            return {
                secret: parsed.secret,
                ...(updatedAt ? { updatedAt } : {}),
                ...(credentialVersion ? { credentialVersion } : {}),
            };
        }
    }
    catch {
        // Legacy/raw secret compatibility. Do not log raw value.
    }
    return { secret: raw };
}
