package dev.rnett.gradle.mcp.tools.skills

import dev.rnett.gradle.mcp.mcp.McpServerComponent
import dev.rnett.gradle.mcp.mcp.ToolCallResult
import dev.rnett.gradle.mcp.tools.ToolNames
import io.github.smiley4.schemakenerator.core.annotations.Description
import kotlinx.serialization.Serializable
import org.slf4j.LoggerFactory
import java.io.File
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.util.zip.ZipInputStream

class SkillTools : McpServerComponent(
    "Skill Tools",
    "Tools for managing Gradle MCP skills."
) {

    companion object {
        private val LOGGER = LoggerFactory.getLogger(SkillTools::class.java)
    }

    @Serializable
    data class InstallSkillsArgs(
        @Description("Providing the absolute path to the authoritative skill installation directory.")
        val directory: String,
        @Description("Replaces existing skills from this MCP server in the target directory.")
        val replaceOld: Boolean = true
    )

    init {
        tool<InstallSkillsArgs, String>(
        ToolNames.INSTALL_GRADLE_SKILLS,
        """
            |Installs or updates the official Gradle MCP skills into the agent's skill directory; provides expert-level workflows for Gradle builds, tests, and dependency management.
            |
            |Provide the absolute path to your agent's skill directory (e.g., `~/.agents/skills`). Skills are extracted as `SKILL.md` files into named subdirectories.
            |Set `replaceOld=true` (default) to replace existing skills from this server and ensure the latest guidance is active.
        """.trimMargin()
    ) { args, _ ->
        val targetDir = File(args.directory)
        if (!targetDir.exists()) {
            if (!targetDir.mkdirs()) {
                throw IllegalStateException("Failed to create target directory: ${args.directory}")
            }
        }

        if (targetDir.isFile) {
            throw IllegalStateException("Target directory is a file: ${targetDir.absolutePath}")
        }

        if (args.replaceOld) {
            // Remove existing skills from this repo to ensure clean update
            val authorUrl = "https://github.com/rnett/gradle-mcp"
            targetDir.listFiles { file -> file.isDirectory }?.forEach { skillDir ->
                val skillFile = File(skillDir, "SKILL.md")
                if (skillFile.exists()) {
                    val content = skillFile.readText()
                    if (content.contains("author: $authorUrl") ||
                        content.contains("author: \"$authorUrl\"") ||
                        content.contains("author: '$authorUrl'")
                    ) {
                        skillDir.deleteRecursively()
                    }
                }
            }
        }

        val classLoader = this::class.java.classLoader

        val installedSkills = mutableSetOf<String>()
        val skippedSkills = mutableSetOf<String>()

        classLoader.getResourceAsStream("skills.zip")?.use { zipStream ->
            ZipInputStream(zipStream).use { zis ->
                var entry = zis.nextEntry
                while (entry != null) {
                    if (!entry.isDirectory) {
                        val entryName = entry.name
                        val skillName = entryName.substringBefore("/")

                        val skillDir = File(targetDir, skillName)
                        val exists = skillDir.exists()

                        if (!exists || (installedSkills.contains(skillName) && !skippedSkills.contains(skillName))) {
                            val targetFile = File(targetDir, entryName)
                            targetFile.parentFile.mkdirs()
                            Files.copy(zis, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
                            installedSkills.add(skillName)
                        } else {
                            skippedSkills.add(skillName)
                        }
                    }
                    entry = zis.nextEntry
                }
            }
        } ?: error("skills.zip resource not found")

        ToolCallResult(buildString {
            if (installedSkills.isNotEmpty()) {
                appendLine("Successfully installed ${installedSkills.size} skills to ${targetDir.absolutePath}:")
                installedSkills.sorted().forEach {
                    appendLine("- $it")
                }
            }
            if (skippedSkills.isNotEmpty()) {
                if (installedSkills.isNotEmpty()) appendLine()
                appendLine("Skipped ${skippedSkills.size} existing skills (use replaceOld=true to replace skills from this server):")
                skippedSkills.sorted().forEach {
                    appendLine("- $it")
                }
            }
        })
    }
    }
}
