import { randomUUID } from "node:crypto";
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
import path from "node:path";
import { keyFor, maskSecret } from "./SecureStore.js";
export class PlaintextDevSecureStore {
    filePath;
    constructor(filePath, mode) {
        this.filePath = filePath;
        if (mode === "production") {
            throw new Error("credential-store-plaintext-production-blocked");
        }
    }
    async get(ref) {
        return (await this.readFile()).records[keyFor(ref)]?.secret;
    }
    async set(ref, secret) {
        const file = await this.readFile();
        file.records[keyFor(ref)] = {
            secret,
            updatedAt: new Date().toISOString(),
            credentialVersion: randomUUID(),
        };
        await this.writeFile(file);
    }
    async delete(ref) {
        const file = await this.readFile();
        delete file.records[keyFor(ref)];
        await this.writeFile(file);
    }
    async status(ref) {
        const record = (await this.readFile()).records[keyFor(ref)];
        if (!record)
            return { ref, state: "missing", backend: "plaintext_dev" };
        return {
            ref,
            state: "available",
            maskedLabel: maskSecret(record.secret),
            updatedAt: record.updatedAt,
            ...(record.credentialVersion
                ? { credentialVersion: record.credentialVersion }
                : {}),
            backend: "plaintext_dev",
        };
    }
    async readFile() {
        try {
            const parsed = JSON.parse(await readFile(this.filePath, "utf8"));
            if (isPlaintextFile(parsed))
                return parsed;
            throw new Error(`Invalid plaintext dev credential file format: ${this.filePath}`);
        }
        catch (error) {
            if (isNodeError(error) && error.code === "ENOENT")
                return { version: 1, records: {} };
            throw error;
        }
    }
    async writeFile(file) {
        await mkdir(path.dirname(this.filePath), { recursive: true, mode: 0o700 });
        const tmpPath = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;
        await writeFile(tmpPath, `${JSON.stringify(file, null, 2)}\n`, {
            mode: 0o600,
        });
        await rename(tmpPath, this.filePath);
    }
}
function isPlaintextFile(value) {
    return (typeof value === "object" &&
        value !== null &&
        "version" in value &&
        value.version === 1 &&
        "records" in value &&
        typeof value.records === "object" &&
        value.records !== null);
}
function isNodeError(error) {
    return error instanceof Error && "code" in error;
}
