## Shared Test Helpers for Resolver Tests
##
## This module provides common utilities for testing the dependency resolver.

import std/[tables, sets, options, strutils]
import ../src/nip/resolver/[
  variant_types,
  dependency_graph
]
import ../src/nip/manifest_parser

# --- Variant Helpers ---

proc makeVariant*(flags: seq[string] = @[]): VariantProfile =
  ## Create a simple variant profile for testing
  var domains = initTable[string, VariantDomain]()
  
  if flags.len > 0:
    var flagSet = initHashSet[string]()
    for flag in flags:
      flagSet.incl(flag)
    
    domains["features"] = VariantDomain(
      name: "features",
      exclusivity: NonExclusive,
      flags: flagSet
    )
  
  result = VariantProfile(
    domains: domains,
    hash: if flags.len > 0: "hash-" & flags.join("-") else: "hash-empty"
  )

proc makeVersion*(major: int = 1, minor: int = 0, patch: int = 0): SemanticVersion =
  ## Create a semantic version for testing
  SemanticVersion(major: major, minor: minor, patch: patch)

# --- PackageTerm Helpers ---

proc makeTerm*(name: string, version: SemanticVersion, 
               variant: VariantProfile, source: string = "test"): PackageTerm =
  ## Create a package term for testing
  let termId = createTermId(name, variant.hash)
  
  PackageTerm(
    id: termId,
    packageName: name,
    version: version,
    variantProfile: variant,
    optional: false,
    source: source
  )

proc makeTerm*(name: string, source: string = "test"): PackageTerm =
  ## Create a package term with default version and variant
  makeTerm(name, makeVersion(), makeVariant(), source)

# --- Graph Builders ---

proc makeChainGraph*(length: int): DependencyGraph =
  ## Create a chain graph: P0 -> P1 -> P2 -> ... -> P(n-1)
  result = newDependencyGraph()
  
  var prevTermId: Option[PackageTermId] = none(PackageTermId)
  
  for i in 0..<length:
    let term = makeTerm("pkg" & $i, makeVersion(1, 0, i))
    result.addTerm(term)
    
    if prevTermId.isSome:
      result.addEdge(DependencyEdge(
        fromTerm: prevTermId.get(),
        toTerm: term.id,
        dependencyType: Required
      ))
    
    prevTermId = some(term.id)

proc makeDiamondGraph*(): DependencyGraph =
  ## Create a diamond graph: A -> B, A -> C, B -> D, C -> D
  result = newDependencyGraph()
  
  let termA = makeTerm("A", makeVersion(1, 0, 0))
  let termB = makeTerm("B", makeVersion(1, 0, 0))
  let termC = makeTerm("C", makeVersion(1, 0, 0))
  let termD = makeTerm("D", makeVersion(1, 0, 0))
  
  result.addTerm(termA)
  result.addTerm(termB)
  result.addTerm(termC)
  result.addTerm(termD)
  
  result.addEdge(DependencyEdge(fromTerm: termA.id, toTerm: termB.id, dependencyType: Required))
  result.addEdge(DependencyEdge(fromTerm: termA.id, toTerm: termC.id, dependencyType: Required))
  result.addEdge(DependencyEdge(fromTerm: termB.id, toTerm: termD.id, dependencyType: Required))
  result.addEdge(DependencyEdge(fromTerm: termC.id, toTerm: termD.id, dependencyType: Required))
