// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later

package space.rcmd.android.sizzle.io

import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.nio.file.Files

/** Round-trip + safety coverage for the whole-app [BackupIo]. */
class BackupIoTest {

    private fun tempDir(): File = Files.createTempDirectory("backup-test").toFile()

    private fun seed(dir: File) {
        File(dir, "songs").mkdirs()
        File(dir, "songs/tune.szg").writeText("SONG-DATA")
        File(dir, "presets/DELAY").mkdirs()
        File(dir, "presets/DELAY/slap.szp").writeText("PRESET-DATA")
        File(dir, "datastore").mkdirs()
        File(dir, "datastore/app_settings.preferences_pb").writeBytes(byteArrayOf(1, 2, 3, 4))
        File(dir, "autosave.sng").writeText("AUTO-DATA")
    }

    @Test fun backupRestoreRoundTripReplacesContent() {
        val source = tempDir().also { seed(it) }
        val zip = ByteArrayOutputStream().also { BackupIo.write(source, it) }.toByteArray()

        // Restore into a dir that already holds different + stale data.
        val target = tempDir()
        File(target, "songs").mkdirs()
        File(target, "songs/stale.szg").writeText("STALE") // not in the backup → must go

        assertTrue(BackupIo.read(target, ByteArrayInputStream(zip)))

        assertEquals("SONG-DATA", File(target, "songs/tune.szg").readText())
        assertFalse("a song absent from the backup is removed", File(target, "songs/stale.szg").exists())
        assertEquals("PRESET-DATA", File(target, "presets/DELAY/slap.szp").readText())
        assertEquals("AUTO-DATA", File(target, "autosave.sng").readText())
        assertArrayEquals(byteArrayOf(1, 2, 3, 4), File(target, "datastore/app_settings.preferences_pb").readBytes())
        assertFalse("staging is cleaned up", File(target, ".restore_tmp").exists())
    }

    @Test fun invalidArchiveLeavesDataIntact() {
        val target = tempDir()
        File(target, "songs").mkdirs()
        File(target, "songs/keep.szg").writeText("KEEP")

        assertFalse(BackupIo.read(target, ByteArrayInputStream("this is not a zip".toByteArray())))
        assertEquals("existing data survives a bad restore file", "KEEP", File(target, "songs/keep.szg").readText())
    }

    @Test fun emptyZipIsRejected() {
        val emptyZip = ByteArrayOutputStream().also { java.util.zip.ZipOutputStream(it).close() }.toByteArray()
        val target = tempDir()
        File(target, "songs").mkdirs()
        File(target, "songs/keep.szg").writeText("KEEP")

        assertFalse(BackupIo.read(target, ByteArrayInputStream(emptyZip)))
        assertEquals("KEEP", File(target, "songs/keep.szg").readText())
    }

    private fun assertArrayEquals(a: ByteArray, b: ByteArray) =
        assertTrue("byte arrays differ", a.contentEquals(b))
}
