## test_variant_profiles.nim
## Tests for variant profile system

import std/[unittest, tables, options, os, strutils]
import ../src/nimpak/variant_profiles
import ../src/nimpak/variant_types
import ../src/nimpak/config

suite "Variant Profile System":

  test "Load fleet-node profile from KDL":
    let profilePath = ".kiro/nip/profiles/fleet-node.kdl"
    if not fileExists(profilePath):
      skip()

    let profile = loadProfile(profilePath)

    check profile.name == "fleet-node"
    check profile.description.len > 0
    check profile.domains.len > 0

    # Check specific domains
    check profile.hasDomain("init")
    check profile.getDomainValues("init") == @["dinit"]

    check profile.hasDomain("security")
    let securityFlags = profile.getDomainValues("security")
    check "pie" in securityFlags
    check "relro" in securityFlags

    # Check compiler flags
    check profile.compilerFlags.cflags.len > 0
    check "-Os" in profile.compilerFlags.cflags

  test "Load gaming-rig profile from KDL":
    let profilePath = ".kiro/nip/profiles/gaming-rig.kdl"
    if not fileExists(profilePath):
      skip()

    let profile = loadProfile(profilePath)

    check profile.name == "gaming-rig"
    check profile.hasDomain("graphics")

    let graphicsFlags = profile.getDomainValues("graphics")
    check "vulkan" in graphicsFlags
    check "wayland" in graphicsFlags

    # Check optimization
    check profile.hasDomain("optimization")
    let optFlags = profile.getDomainValues("optimization")
    check "lto" in optFlags
    check "march-native" in optFlags

  test "Load ml-workstation profile from KDL":
    let profilePath = ".kiro/nip/profiles/ml-workstation.kdl"
    if not fileExists(profilePath):
      skip()

    let profile = loadProfile(profilePath)

    check profile.name == "ml-workstation"
    check profile.hasDomain("runtime")

    let runtimeFlags = profile.getDomainValues("runtime")
    check "python" in runtimeFlags

    check profile.hasDomain("developer")
    let devFlags = profile.getDomainValues("developer")
    check "debugger" in devFlags
    check "lsp" in devFlags

  test "Merge profile with domain overrides":
    var baseProfile = newVariantProfile("base", "Base profile")
    baseProfile.domains["init"] = @["systemd"]
    baseProfile.domains["graphics"] = @["X"]
    baseProfile.compilerFlags.cflags = "-O2"

    var overrides = initTable[string, seq[string]]()
    overrides["init"] = @["dinit"]  # Override init
    overrides["audio"] = @["pipewire"]  # Add new domain

    let merged = mergeProfileWithOverrides(baseProfile, overrides)

    check merged.getDomainValues("init") == @["dinit"]  # Overridden
    check merged.getDomainValues("graphics") == @["X"]  # Preserved
    check merged.getDomainValues("audio") == @["pipewire"]  # Added
    check merged.compilerFlags.cflags == "-O2"  # Preserved

  test "Merge profile with compiler flag overrides":
    var baseProfile = newVariantProfile("base", "Base profile")
    baseProfile.compilerFlags.cflags = "-O2"
    baseProfile.compilerFlags.ldflags = "-Wl,-O1"

    var overrideFlags = CompilerFlags(
      cflags: "-O3 -march=native",
      ldflags: "",  # Empty, should not override
      makeflags: "-j16"  # New flag
    )

    let merged = mergeProfileWithOverrides(
      baseProfile,
      initTable[string, seq[string]](),
      some(overrideFlags)
    )

    check merged.compilerFlags.cflags == "-O3 -march=native"  # Overridden
    check merged.compilerFlags.ldflags == "-Wl,-O1"  # Preserved (empty override)
    check merged.compilerFlags.makeflags == "-j16"  # Added

  test "Merge two profiles":
    var baseProfile = newVariantProfile("base", "Base profile")
    baseProfile.domains["init"] = @["systemd"]
    baseProfile.domains["graphics"] = @["X"]
    baseProfile.compilerFlags.cflags = "-O2"

    var overlayProfile = newVariantProfile("overlay", "Overlay profile")
    overlayProfile.domains["init"] = @["dinit"]  # Override
    overlayProfile.domains["audio"] = @["pipewire"]  # Add
    overlayProfile.compilerFlags.cflags = "-O3"  # Override
    overlayProfile.compilerFlags.ldflags = "-Wl,-O1"  # Add

    let merged = mergeProfiles(baseProfile, overlayProfile)

    check merged.name == "overlay"  # Takes overlay name
    check merged.getDomainValues("init") == @["dinit"]  # Overridden
    check merged.getDomainValues("graphics") == @["X"]  # Preserved from base
    check merged.getDomainValues("audio") == @["pipewire"]  # Added from overlay
    check merged.compilerFlags.cflags == "-O3"  # Overridden
    check merged.compilerFlags.ldflags == "-Wl,-O1"  # Added

  test "Profile string representation":
    var profile = newVariantProfile("test", "Test profile")
    profile.domains["init"] = @["dinit"]
    profile.domains["graphics"] = @["wayland", "vulkan"]
    profile.compilerFlags.cflags = "-O3"
    profile.compilerFlags.makeflags = "-j8"

    let str = $profile

    check "test" in str
    check "Test profile" in str
    check "init" in str
    check "dinit" in str
    check "graphics" in str
    check "wayland" in str
    check "CFLAGS" in str
    check "-O3" in str

  test "List domains in profile":
    var profile = newVariantProfile("test", "Test profile")
    profile.domains["init"] = @["dinit"]
    profile.domains["graphics"] = @["wayland"]
    profile.domains["audio"] = @["pipewire"]

    let domains = profile.listDomains()

    check domains.len == 3
    check "init" in domains
    check "graphics" in domains
    check "audio" in domains

  test "Profile error handling - missing file":
    expect ProfileParseError:
      discard loadProfile("nonexistent.kdl")

  test "Profile error handling - invalid KDL":
    # Create a temporary invalid KDL file
    let tempPath = "/tmp/test_invalid_profile.kdl"
    writeFile(tempPath, "invalid { kdl syntax")

    try:
      expect CatchableError:  # KDL parse errors are caught as ProfileParseError
        discard loadProfile(tempPath)
    finally:
      removeFile(tempPath)

  test "Profile error handling - missing profile node":
    # Create a KDL file without a profile node
    let tempPath = "/tmp/test_no_profile.kdl"
    writeFile(tempPath, """
      config {
        value "test"
      }
    """)

    try:
      expect ProfileParseError:
        discard loadProfile(tempPath)
    finally:
      removeFile(tempPath)

when isMainModule:
  echo "Running variant profile tests..."
