## test_recipe_parser.nim
## Unit tests for recipe parser

import std/[unittest, os, json]
import ../src/nimpak/build/recipe_parser

suite "Recipe Binary":
  test "Create binary":
    var binary = RecipeBinary()
    binary.name = "test-binary"
    binary.url = "https://example.com/binary"
    binary.checksum = "blake2b-abc123"
    binary.size = 1024
    binary.executable = true

    check:
      binary.name == "test-binary"
      binary.url == "https://example.com/binary"
      binary.checksum == "blake2b-abc123"
      binary.size == 1024
      binary.executable == true

  test "Binary to JSON":
    var binary = RecipeBinary()
    binary.name = "test"
    binary.url = "https://example.com/test"
    binary.checksum = "blake2b-123"
    binary.size = 2048
    binary.executable = false

    let jsonNode = binary.toJson()

    check:
      jsonNode["name"].getStr() == "test"
      jsonNode["url"].getStr() == "https://example.com/test"
      jsonNode["checksum"].getStr() == "blake2b-123"
      jsonNode["size"].getInt() == 2048
      jsonNode["executable"].getBool() == false

  test "Binary from JSON":
    let jsonStr = """
    {
      "name": "imported",
      "url": "https://example.com/imported",
      "checksum": "blake2b-456",
      "size": 4096,
      "executable": true
    }
    """

    let jsonNode = parseJson(jsonStr)
    let binary = fromJson(jsonNode, RecipeBinary)

    check:
      binary.name == "imported"
      binary.url == "https://example.com/imported"
      binary.checksum == "blake2b-456"
      binary.size == 4096
      binary.executable == true

suite "Recipe Archive":
  test "Create archive":
    var archive = RecipeArchive()
    archive.name = "test-archive"
    archive.url = "https://example.com/archive.tar.gz"
    archive.checksum = "blake2b-xyz"
    archive.size = 10240
    archive.extractTo = "/opt/test"

    check:
      archive.name == "test-archive"
      archive.url == "https://example.com/archive.tar.gz"
      archive.checksum == "blake2b-xyz"
      archive.size == 10240
      archive.extractTo == "/opt/test"

  test "Archive to JSON":
    var archive = RecipeArchive()
    archive.name = "archive"
    archive.url = "https://example.com/archive.tar.gz"
    archive.checksum = "blake2b-789"
    archive.size = 20480
    archive.extractTo = "/usr/local"

    let jsonNode = archive.toJson()

    check:
      jsonNode["name"].getStr() == "archive"
      jsonNode["url"].getStr() == "https://example.com/archive.tar.gz"
      jsonNode["extractTo"].getStr() == "/usr/local"

suite "Recipe Platform":
  test "Create platform":
    var platform = RecipePlatform()
    platform.arch = paX86_64
    platform.os = "linux"

    check:
      platform.arch == paX86_64
      platform.os == "linux"

  test "Platform with binaries":
    var platform = RecipePlatform()
    platform.arch = paAarch64
    platform.os = "linux"

    var binary = RecipeBinary()
    binary.name = "test"
    binary.url = "https://example.com/test"
    binary.checksum = "blake2b-123"
    binary.size = 1024
    binary.executable = true

    platform.binaries.add(binary)

    check:
      platform.binaries.len == 1
      platform.binaries[0].name == "test"

  test "Platform to JSON":
    var platform = RecipePlatform()
    platform.arch = paX86_64
    platform.os = "linux"

    let jsonNode = platform.toJson()

    check:
      jsonNode["arch"].getStr() == "x86_64"
      jsonNode["os"].getStr() == "linux"
      jsonNode["binaries"].kind == JArray
      jsonNode["archives"].kind == JArray

suite "Recipe Dependency":
  test "Create dependency":
    var dep = RecipeDependency()
    dep.name = "git"
    dep.kind = "system"
    dep.version = ">=2.0"
    dep.required = true

    check:
      dep.name == "git"
      dep.kind == "system"
      dep.version == ">=2.0"
      dep.required == true

  test "Dependency to JSON":
    var dep = RecipeDependency()
    dep.name = "curl"
    dep.kind = "system"
    dep.version = ""
    dep.required = false

    let jsonNode = dep.toJson()

    check:
      jsonNode["name"].getStr() == "curl"
      jsonNode["kind"].getStr() == "system"
      jsonNode["required"].getBool() == false

suite "Recipe Install":
  test "Create install":
    var install = RecipeInstall()
    install.script = "scripts/install.sh"
    install.verifyScript = "scripts/verify.sh"
    install.postInstall = "scripts/post.sh"

    check:
      install.script == "scripts/install.sh"
      install.verifyScript == "scripts/verify.sh"
      install.postInstall == "scripts/post.sh"

  test "Install to JSON":
    var install = RecipeInstall()
    install.script = "install.sh"
    install.verifyScript = "verify.sh"
    install.postInstall = ""

    let jsonNode = install.toJson()

    check:
      jsonNode["script"].getStr() == "install.sh"
      jsonNode["verifyScript"].getStr() == "verify.sh"

suite "Recipe Metadata":
  test "Create metadata":
    var metadata = RecipeMetadata()
    metadata.author = "Test Author"
    metadata.license = "MIT"
    metadata.updated = "2024-11-16"
    metadata.homepage = "https://example.com"
    metadata.issues = "https://example.com/issues"

    check:
      metadata.author == "Test Author"
      metadata.license == "MIT"
      metadata.updated == "2024-11-16"

  test "Metadata to JSON":
    var metadata = RecipeMetadata()
    metadata.author = "Author"
    metadata.license = "Apache-2.0"
    metadata.updated = "2024-01-01"
    metadata.homepage = "https://test.com"
    metadata.issues = "https://test.com/issues"

    let jsonNode = metadata.toJson()

    check:
      jsonNode["author"].getStr() == "Author"
      jsonNode["license"].getStr() == "Apache-2.0"

suite "Full Recipe":
  test "Create recipe":
    var recipe = Recipe()
    recipe.name = "test-tool"
    recipe.version = "1.0.0"
    recipe.description = "Test tool"
    recipe.toolType = "test"

    check:
      recipe.name == "test-tool"
      recipe.version == "1.0.0"
      recipe.description == "Test tool"
      recipe.toolType == "test"

  test "Recipe to JSON":
    var recipe = Recipe()
    recipe.name = "toolType"
    recipe.version = "2.0.0"
    recipe.description = "A tool"
    recipe.toolType = "toolType"

    let jsonNode = recipe.toJson()

    check:
      jsonNode["name"].getStr() == "toolType"
      jsonNode["version"].getStr() == "2.0.0"
      jsonNode["description"].getStr() == "A tool"
      jsonNode["toolType"].getStr() == "toolType"

  test "Recipe export and import":
    var recipe = Recipe()
    recipe.name = "export-test"
    recipe.version = "1.0.0"
    recipe.description = "Export test"
    recipe.toolType = "test"

    let tempFile = getTempDir() / "test-recipe.json"

    # Export
    let exported = recipe.exportToJson(tempFile)
    check:
      exported == true
      fileExists(tempFile)

    # Import
    let imported = importFromJson(tempFile)
    check:
      imported.name == "export-test"
      imported.version == "1.0.0"
      imported.description == "Export test"
      imported.toolType == "test"

    removeFile(tempFile)

echo "✅ All recipe parser tests completed"
