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

package space.rcmd.android.sizzle.io

import space.rcmd.android.sizzle.ui.theme.RetroPalette
import java.io.File

/**
 * On-device library of USER colour themes, stored as plain [ThemeIo] text:
 *
 *     <baseDir>/Sunset.szt          ← a saved/imported theme
 *     <baseDir>/.export/…​.szt       ← transient copy written for sharing
 *
 * The two built-in themes ([RetroPalette.ALL]) are NOT stored here — they live in
 * code and can never be deleted. This library only holds themes the user imports,
 * so `delete` here can only ever remove a user theme.
 */
class ThemeLibrary(private val baseDir: File) {

    /** Names (without extension) of the stored user themes, alphabetically. */
    fun list(): List<String> =
        baseDir.listFiles { f -> f.isFile && f.name.endsWith(EXT) }
            ?.map { it.name.removeSuffix(EXT) }
            ?.sorted()
            ?: emptyList()

    private fun file(name: String): File = File(baseDir.apply { mkdirs() }, sanitize(name) + EXT)

    /** Save [palette] as a user theme (named after it). Returns the written file. */
    fun save(palette: RetroPalette): File = file(palette.name).apply { writeText(ThemeIo.export(palette)) }

    /** Load a stored user theme by name, or null if missing/unparseable. */
    fun load(name: String): RetroPalette? =
        file(name).takeIf { it.exists() }?.let { runCatching { ThemeIo.parse(it.readText()) }.getOrNull() }

    /** Every stored user theme, skipping any that fail to parse. */
    fun loadAll(): List<RetroPalette> = list().mapNotNull { load(it) }

    /** Delete a stored user theme. Returns true if it existed. */
    fun delete(name: String): Boolean = file(name).let { if (it.exists()) it.delete() else false }

    /** Import theme [text] (from a picked file): parse, persist to the library, and
     *  return the palette — or null if the text isn't a valid theme. */
    fun importText(text: String): RetroPalette? {
        val palette = runCatching { ThemeIo.parse(text) }.getOrNull() ?: return null
        save(palette)
        return palette
    }

    /** Write a one-off `.szt` to a shareable sub-dir and return the file (kept out of
     *  the library list, like [SongLibrary.writeExport]). */
    fun writeExport(palette: RetroPalette): File {
        val dir = File(baseDir, EXPORT_DIR).apply { mkdirs() }
        return File(dir, sanitize(palette.name) + EXT).apply { writeText(ThemeIo.export(palette)) }
    }

    private fun sanitize(name: String): String =
        name.trim().replace(Regex("[^A-Za-z0-9._ -]"), "_").ifBlank { "theme" }

    private companion object {
        const val EXT = ".szt"
        const val EXPORT_DIR = ".export"
    }
}
