import { mkdir, appendFile } from "node:fs/promises";
import path from "node:path";
function jsonReplacer(_key, value) {
    return typeof value === "bigint" ? value.toString() : value;
}
function stringifyForLog(value) {
    return JSON.stringify(value, jsonReplacer);
}
function formatValue(value) {
    if (value === null || value === undefined) {
        return "-";
    }
    if (["string", "number", "boolean", "bigint"].includes(typeof value)) {
        return String(value);
    }
    return JSON.stringify(value, jsonReplacer, 2)
        .split("\n")
        .map((line, index) => (index === 0 ? line : `    ${line}`))
        .join("\n");
}
function formatConsoleRecord(timestamp, level, message, data) {
    const tag = level.toUpperCase().padEnd(5, " ");
    const lines = [`[${timestamp}] ${tag} ${message}`];
    if (data && typeof data === "object" && !Array.isArray(data)) {
        for (const [key, value] of Object.entries(data)) {
            lines.push(`  ${key}: ${formatValue(value)}`);
        }
    }
    else if (data !== undefined) {
        lines.push(`  details: ${formatValue(data)}`);
    }
    return lines.join("\n");
}
export class Logger {
    logFile;
    constructor(logFile) {
        this.logFile = logFile;
    }
    async write(level, message, data) {
        const record = {
            timestamp: new Date().toISOString(),
            level,
            message,
            data
        };
        const line = stringifyForLog(record);
        const printable = formatConsoleRecord(record.timestamp, level, message, data);
        if (level === "error") {
            console.error(printable);
        }
        else if (level === "warn") {
            console.warn(printable);
        }
        else {
            console.log(printable);
        }
        await mkdir(path.dirname(this.logFile), { recursive: true });
        await appendFile(this.logFile, `${line}\n`, "utf8");
    }
}
