# tests/test_grafting.nim
# Unit tests for grafting engine

import unittest, os, json
import ../src/nimpak/grafting
import ../src/nimpak/adapters/pacman
import ../src/nip/types

suite "Grafting Engine Tests":

  setup:
    let tempDir = getTempDir() / "nimpak_test_grafting"
    if dirExists(tempDir):
      removeDir(tempDir)
    createDir(tempDir)

  teardown:
    let tempDir = getTempDir() / "nimpak_test_grafting"
    if dirExists(tempDir):
      removeDir(tempDir)

  test "Grafting engine initialization":
    let engineResult = initGraftingEngine()
    check engineResult.isOk

    let engine = engineResult.get()
    check engine.config.enabled == true
    check engine.adapters.len == 0
    check engine.transactions.len == 0

  test "Pacman adapter registration":
    var engineResult = initGraftingEngine()
    check engineResult.isOk

    var engine = engineResult.get()
    let adapter = newPacmanAdapter()

    let registerResult = engine.registerAdapter(adapter)
    check registerResult.isOk
    check engine.adapters.len == 1
    check "pacman" in engine.adapters

  test "Pacman adapter configuration":
    let config = %*{
      "mirror_url": "https://custom.mirror.org",
      "cache_dir": "/custom/cache",
      "aur_enabled": false
    }

    let adapter = newPacmanAdapter(config)
    check adapter.mirrorUrl == "https://custom.mirror.org"
    check adapter.cacheDir == "/custom/cache"
    check adapter.aurEnabled == false

  test "Grafting status reporting":
    let engineResult = initGraftingEngine()
    check engineResult.isOk

    let engine = engineResult.get()
    let status = engine.getGraftingStatus()

    check status.hasKey("enabled")
    check status.hasKey("adapters")
    check status.hasKey("cache")
    check status.hasKey("transactions")

  test "Graft hash calculation":
    let hash1 = calculateGraftHash("test-package", "pacman", now())
    let hash2 = calculateGraftHash("test-package", "pacman", now())

    check hash1.startsWith("graft-")
    check hash1 != hash2  # Different timestamps should produce different hashes

  test "Grafted package listing":
    let engineResult = initGraftingEngine()
    check engineResult.isOk

    let engine = engineResult.get()
    let packages = engine.listGraftedPackages()
    check packages.len == 0  # No packages grafted yet

  test "Cache cleanup":
    var engineResult = initGraftingEngine()
    check engineResult.isOk

    var engine = engineResult.get()

    # Add some test metadata
    let oldMetadata = GraftedPackageMetadata(
      packageName: "old-package",
      version: "1.0",
      source: "test",
      graftedAt: now() - initDuration(days = 10),
      originalHash: "test-hash",
      graftHash: "graft-test",
      buildLog: "test log",
      provenance: ProvenanceInfo()
    )

    engine.cache.metadata["old-package"] = oldMetadata

    let cleanupResult = engine.cleanupGraftCache(initDuration(days = 5))
    check cleanupResult.isOk
    check cleanupResult.get() == 1  # Should have cleaned up 1 entry

suite "Pacman Adapter Tests":

  test "Pacman adapter creation":
    let adapter = newPacmanAdapter()
    check adapter.name == "pacman"
    check adapter.enabled == true
    check adapter.priority == 30
    check adapter.aurEnabled == true

  test "Package validation (mock)":
    let adapter = newPacmanAdapter()

    # This test would normally require pacman to be installed
    # For now, just test the method exists and returns a result
    let validationResult = adapter.validatePackage("nonexistent-package")
    check validationResult.isOk or validationResult.isErr  # Either is fine for mock

  test "Package info retrieval (mock)":
    let adapter = newPacmanAdapter()

    # This test would normally require pacman to be installed
    # For now, just test the method exists and returns a result
    let infoResult = adapter.getPackageInfo("nonexistent-package")
    check infoResult.isOk or infoResult.isErr  # Either is fine for mock