package de.arxsilex.maptools.converter.desktop

import java.nio.file.Files
import java.nio.file.Path
import java.util.Comparator
import kotlin.io.path.createTempDirectory
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class PlatformDirectoriesTest {
    @Test
    fun `uses executable directory for every persistent runtime folder`() {
        val executableDirectory = Path.of("portable-test", "MapTools").toAbsolutePath().normalize()
        val root = PlatformDirectories.applicationDirectory(
            configuredRoot = null,
            jpackageApplicationPath = executableDirectory.resolve("ArxSilex MapTools Converter").toString(),
            workingDirectory = Path.of("ignored-working-directory").toAbsolutePath().toString(),
        )

        assertEquals(executableDirectory, root)
        assertEquals(executableDirectory.resolve("cache/preview"), PlatformDirectories.previewCacheDirectory(root))
        assertEquals(executableDirectory.resolve("cache/conversion"), PlatformDirectories.conversionCacheDirectory(root))
        assertEquals(executableDirectory.resolve("logs"), PlatformDirectories.logDirectory(root))
        assertEquals(executableDirectory.resolve("temp"), PlatformDirectories.temporaryRootDirectory(root))
    }

    @Test
    fun `configured portable root wins over launcher and working directory`() {
        val configuredRoot = Path.of("configured-portable-root").toAbsolutePath().normalize()
        val root = PlatformDirectories.applicationDirectory(
            configuredRoot = configuredRoot.toString(),
            jpackageApplicationPath = Path.of("ignored-launcher").toAbsolutePath().toString(),
            workingDirectory = Path.of("ignored-working-directory").toAbsolutePath().toString(),
        )

        assertEquals(configuredRoot, root)
    }

    @Test
    fun `prepares portable folders removes legacy data and deletes session temp on shutdown`() {
        val parent = createTempDirectory("maptools-portable-test-")
        val root = parent.resolve("portable")
        val legacy = parent.resolve("ArxSilex").resolve("MapTools Converter")
        Files.createDirectories(legacy.resolve("cache"))
        Files.write(legacy.resolve("cache").resolve("old.bin"), byteArrayOf(1, 2, 3))
        Files.createDirectories(root.resolve("cache/conversion/selection-stale"))
        Files.write(root.resolve("cache/conversion/selection-stale/data.bin"), byteArrayOf(4, 5))
        try {
            val runtime = PlatformDirectories.prepareRuntime(root, listOf(legacy), processId = 987_654_321L)

            assertTrue(Files.isDirectory(root.resolve("cache/preview")))
            assertTrue(Files.isDirectory(root.resolve("cache/conversion")))
            assertTrue(Files.isDirectory(root.resolve("logs")))
            assertTrue(Files.isDirectory(runtime.sessionTemporaryDirectory))
            assertEquals(3L, runtime.removedLegacyBytes)
            assertFalse(Files.exists(legacy))
            assertFalse(Files.exists(root.resolve("cache/conversion/selection-stale")))

            PlatformDirectories.cleanupRuntime(runtime)

            assertFalse(Files.exists(root.resolve("temp")))
            assertTrue(Files.isDirectory(root.resolve("cache")))
            assertTrue(Files.isDirectory(root.resolve("logs")))
        } finally {
            deleteTree(parent)
        }
    }

    @Test
    fun `reports insufficient portable storage using conservative conversion estimate`() {
        val gibibyte = 1024L * 1024L * 1024L
        val status = PlatformDirectories.conversionStorageStatus(
            sourceBytes = gibibyte,
            applicationDirectory = Path.of("D:/portable"),
            usableBytes = 2L * gibibyte,
        )

        assertFalse(status.hasEnoughSpace)
        assertTrue(status.requiredBytes > 6L * gibibyte)
    }

    private fun deleteTree(path: Path) {
        if (!Files.exists(path)) return
        Files.walk(path).use { entries ->
            entries.sorted(Comparator.reverseOrder()).forEach(Files::deleteIfExists)
        }
    }
}
