package cclotus.cloud.gateway.util

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
import org.springframework.core.io.FileSystemResourceLoader
import org.springframework.stereotype.Component
import java.io.File
import java.io.FileNotFoundException
import java.nio.file.Files
import java.util.concurrent.ConcurrentHashMap
import javax.annotation.PostConstruct

@Component
@ConditionalOnClass(ThymeleafProperties::class)
class TemplateManager(val properties: ThymeleafProperties) {

    private val htmlTemplatesCache = ConcurrentHashMap<String, Boolean>()

    @PostConstruct
    fun cacheTemplates() {
        val templateRootDir = FileSystemResourceLoader().getResource(properties.prefix).file

        require(templateRootDir.exists()) { "The provided root directory '${properties.prefix}' does not exist." }
        require(templateRootDir.isDirectory) { "The provided root directory '${properties.prefix}' is not a valid directory path." }

        try {
            Files.walk(templateRootDir.toPath())
                .parallel()
                .filter { Files.isRegularFile(it) && it.toString().endsWith(".html", ignoreCase = true) }
                .forEach {
                    val relativePath = templateRootDir.toPath().relativize(it).toString()
                    htmlTemplatesCache.putIfAbsent(relativePath, true)
                }
        } catch (e: Exception) {
            e.printStackTrace()
            throw RuntimeException("Failed to cache HTML files. Root directory: '${properties.prefix}'.", e)
        }
    }

    fun getTemplate(catalogType: String, catalogAlias: String?, postId: String?, postAlias: String?, view: String?): String {
        return if (view != null) {
            getViewTemplate(view)
        } else {
            val filePaths = buildCandidateTemplatePaths(catalogType, catalogAlias, postId, postAlias)
            findMatchedTemplate(filePaths)
        }
    }

    private fun getViewTemplate(view: String): String {
        val viewPath = "$view.html"
        return if (htmlTemplatesCache.containsKey(viewPath)) {
            viewPath
        } else {
            throw FileNotFoundException("Template file '$viewPath' does not exist in cache.")
        }
    }

    private fun buildCandidateTemplatePaths(catalogType: String, catalogAlias: String?, postId: String?, postAlias: String?): List<String> {
        val filePaths = mutableListOf<String>()
        catalogAlias?.let { catalog ->
            val post = postId ?: postAlias ?: ""
            filePaths.add("$catalogType/$catalog/$post.html")
            filePaths.add("$catalogType/$catalog/default.html")
            filePaths.add("$catalogType/$catalog.html")
            filePaths.add("$catalogType/default.html")
            filePaths.add("$catalog.html")
        }
        filePaths.add("$catalogType.html")
        filePaths.add("default.html")
        return filePaths.map { convertPathToOsSeparator(it) }
    }

    private fun findMatchedTemplate(filePaths: List<String>): String {
        for (filePath in filePaths) {
            htmlTemplatesCache[filePath]?.let { isFile ->
                if (isFile) {
                    return filePath
                }
            }
        }
        throw FileNotFoundException("No valid template file found in ${filePaths.joinToString(", ")}")
    }

    private fun convertPathToOsSeparator(path: String): String {
        val osSeparator = File.separator // 获取当前操作系统的路径分割符
        return path.replace('/', osSeparator[0]) // 将路径中的斜杠替换为操作系统路径分割符
    }
}
