import assert from 'node:assert';


// IMPORTANT: this file is required from the migration logic. avoid requires

// note: returns shallow copy. use structuredClone() on top to get a deep copy
function pick(obj, keys) {
    assert(Array.isArray(keys));

    return Object.fromEntries(Object.entries(obj).filter(([key]) => keys.includes(key)));
}

// note: returns shallow copy. use structuredClone() on top to get a deep copy
function omit(obj, keys) {
    assert(Array.isArray(keys));

    return Object.fromEntries(Object.entries(obj).filter(([key]) => !keys.includes(key)));
}

function intersection(arr1, arr2) {
    assert(Array.isArray(arr1));
    assert(Array.isArray(arr2));

    return arr1.filter(value => arr2.includes(value));
}

// can be arrays or objects
function isEqual(val1, val2) {
    if (val1 === val2) return true;

    if (Array.isArray(val1) && Array.isArray(val2)) {
        if (val1.length !== val2.length) return false;
        return val1.every((item, index) => isEqual(item, val2[index]));
    } else if (val1 !== null && typeof val1 === 'object' && val2 !== null && typeof val2 === 'object') {
        const keys1 = Object.keys(val1), keys2 = Object.keys(val2);
        if (keys1.length !== keys2.length) return false;
        return keys1.every(key => isEqual(val1[key], val2[key])); // Recursively compare object properties
    } else {
        return false;
    }
}

function difference(array, values) {
    assert(Array.isArray(array));
    assert(Array.isArray(values));

    const valueSet = new Set(values);
    return array.filter(item => !valueSet.has(item));
}

export default {
    pick,
    omit,
    intersection,
    isEqual,
    difference
};
