package com.correx.infrastructure.tools.filesystem

import com.correx.core.events.events.ToolRequest
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import com.correx.core.events.types.ToolInvocationId
import com.correx.core.tools.contract.ToolResult
import com.correx.core.tools.contract.ValidationResult
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import java.nio.file.Files
import java.util.*

class FileDeleteToolTest {

    private val invocationId = ToolInvocationId(UUID.randomUUID().toString())

    private fun createRequest(parameters: Map<String, String>): ToolRequest = ToolRequest(
        invocationId = invocationId,
        sessionId = SessionId(UUID.randomUUID().toString()),
        stageId = StageId(UUID.randomUUID().toString()),
        toolName = "file_delete",
        parameters = parameters,
    )

    @Test
    fun `validateRequest returns Valid for existing file in allowed directory`(): Unit = runBlocking {
        val tempDir = Files.createTempDirectory("file_delete_test")
        val filePath = tempDir.resolve("existing.txt")
        Files.writeString(filePath, "content")
        val tool = FileDeleteTool(allowedPaths = setOf(tempDir))
        assertEquals(ValidationResult.Valid, tool.validateRequest(createRequest(mapOf("path" to filePath.toString()))))
    }

    @Test
    fun `validateRequest returns Invalid for missing path with actionable message`(): Unit = runBlocking {
        val tempDir = Files.createTempDirectory("file_delete_test")
        val tool = FileDeleteTool(allowedPaths = setOf(tempDir))
        val result = tool.validateRequest(createRequest(emptyMap()))
        assertTrue(result is ValidationResult.Invalid)
        assertTrue((result as ValidationResult.Invalid).reason.contains("Missing 'path'"))
    }

    @Test
    fun `validateRequest returns Invalid for disallowed path`(): Unit = runBlocking {
        val tempDir = Files.createTempDirectory("file_delete_test")
        val otherDir = Files.createTempDirectory("other_dir")
        val tool = FileDeleteTool(allowedPaths = setOf(tempDir))
        val result = tool.validateRequest(createRequest(mapOf("path" to otherDir.resolve("x.txt").toString())))
        assertTrue(result is ValidationResult.Invalid)
        assertTrue((result as ValidationResult.Invalid).reason.contains("is not in the allowed list"))
    }

    @Test
    fun `execute deletes an existing file`(): Unit = runBlocking {
        val tempDir = Files.createTempDirectory("file_delete_test")
        val filePath = tempDir.resolve("to_delete.txt")
        Files.writeString(filePath, "content to delete")
        val tool = FileDeleteTool(allowedPaths = setOf(tempDir))

        val result = tool.execute(createRequest(mapOf("path" to filePath.toString())))

        assertTrue(result is ToolResult.Success)
        assertTrue((result as ToolResult.Success).output.startsWith("File deleted successfully: $filePath"))
        assertFalse(Files.exists(filePath))
    }

    @Test
    fun `execute returns Failure for deleting non-existent file`(): Unit = runBlocking {
        val tempDir = Files.createTempDirectory("file_delete_test")
        val filePath = tempDir.resolve("non_existent.txt")
        val tool = FileDeleteTool(allowedPaths = setOf(tempDir))

        val result = tool.execute(createRequest(mapOf("path" to filePath.toString())))

        assertTrue(result is ToolResult.Failure)
        val failure = result as ToolResult.Failure
        assertEquals("File not found: $filePath", failure.reason)
        assertFalse(failure.recoverable)
    }
}
