/* eslint-disable @typescript-eslint/no-explicit-any */
// Deep key case conversion for plain JSON-like values.

export type CaseMode = "snake" | "camel";

const isPlainObject = (v: any) =>
    v !== null && typeof v === "object" && !Array.isArray(v) && Object.prototype.toString.call(v) === "[object Object]";

function toSnakeKey(k: string): string {
    return k
        .replace(/([A-Z])/g, "_$1")
        .replace(/[-\s]+/g, "_")
        .toLowerCase();
}

function toCamelKey(k: string): string {
    return k.replace(/[_-\s]+([a-zA-Z0-9])/g, (_, c: string) => c.toUpperCase());
}

/** Converts keys of objects deeply, leaving arrays/primitives intact.
 *  Special-case: preserve keys that start with "@" (e.g. "@type") as-is.
 */
export function deepConvertKeys<T = any>(input: T, mode: CaseMode): T {
    if (Array.isArray(input)) {
        return input.map((x) => deepConvertKeys(x, mode)) as any;
    }
    if (isPlainObject(input)) {
        const out: any = {};
        for (const [k, v] of Object.entries(input as any)) {
            const newKey = k.startsWith("@") ? k : mode === "snake" ? toSnakeKey(k) : toCamelKey(k);
            out[newKey] = deepConvertKeys(v as any, mode);
        }
        return out;
    }
    return input;
}