;(function () {
    let backup = context.data
    const updateLogs = compareAndUpdateEntry(backup?.entry, backup?.collectionName, backup?.versionNr - 1)
    backup.updateLogs = updateLogs
    return { data: backup }

    function compareAndUpdateEntry(entry, collectionName, versionNr) {
        let updateLogs
        if (versionNr == 0) {
            updateLogs = getUpdateLogs({}, entry)
        }
        delete entry.updateTime
        let previousEntry = context.db.find("backups", {
            filter: { entryId: context.data.entryId, versionNr, collectionName },
        })[0]
        if (!previousEntry) {
            console.error("No previous entry found")
            updateLogs = getUpdateLogs({}, entry)
        } else {
            delete previousEntry.updateTime
            updateLogs = getUpdateLogs(previousEntry.entry, entry)
        }
        console.log(context.json.stringify(previousEntry?.entry), context.json.stringify(entry))

        return updateLogs
    }

    function filterValidObjects(array) {
        return array.filter((object) => {
            for (let key in object) {
                if (typeof object[key] !== "string" && object[key] !== null) {
                    return false
                }
            }
            return true
        })
    }
    function getUpdateLogs(oldObj = {}, newObj = {}, path = "") {
        let updateLogs = []
        const ignoredKeys = ["id", "insertTime", "updateTime"]
        const allKeys = new Set([...Object.keys(oldObj), ...Object.keys(newObj)])

        allKeys.forEach((key) => {
            if (ignoredKeys.includes(key)) return

            const newPath = path ? `${path}.${key}` : key
            const oldVal = oldObj.hasOwnProperty(key) ? oldObj[key] : ""
            const newVal = newObj.hasOwnProperty(key) ? newObj[key] : ""

            // Handle Arrays
            if (Array.isArray(oldVal) || Array.isArray(newVal)) {
                const oldArr = oldVal || []
                const newArr = newVal || []

                for (let i = 0; i < Math.max(oldArr.length, newArr.length); i++) {
                    const itemPath = `${newPath}[${i}]`

                    if (oldArr[i] !== newArr[i]) {
                        if (typeof oldArr[i] === "object" || typeof newArr[i] === "object") {
                            const arrUpdates = getUpdateLogs(oldArr[i], newArr[i], itemPath)
                            updateLogs = updateLogs.concat(arrUpdates)
                        } else {
                            updateLogs.push({
                                field: itemPath,
                                previous: oldArr[i] === undefined ? "" : oldArr[i].toString(),
                                current: newArr[i] === undefined ? "" : newArr[i].toString(),
                            })
                        }
                    }
                }
            }
            // Handle nested objects but not arrays
            else if (
                (typeof oldVal === "object" && oldVal !== null) ||
                (typeof newVal === "object" && newVal !== null)
            ) {
                const nestedUpdates = getUpdateLogs(oldVal || {}, newVal || {}, newPath)
                updateLogs = updateLogs.concat(nestedUpdates)
            }
            // Handle primitive types
            else if (oldVal !== newVal) {
                updateLogs.push({
                    field: newPath,
                    previous: oldVal.toString(),
                    current: newVal.toString(),
                })
            }
        })

        return filterValidObjects(updateLogs)
    }
})()
