## Example: Profile Resolver Operations
##
## This example demonstrates how to profile actual resolver operations
## to identify performance bottlenecks and optimization opportunities.

import ../src/nip/resolver/profiler
import ../src/nip/resolver/types
import ../src/nip/resolver/variant_unification
import ../src/nip/resolver/graph_builder
import ../src/nip/resolver/topological_sort
import ../src/nip/resolver/optimizations
import times
import strformat

# ============================================================================
# Example Resolver Operations
# ============================================================================

proc simulateVariantUnification() =
  ## Simulate variant unification operations
  
  let opId = startOperation(VariantUnification, "unify-nginx")
  
  let v1 = VariantDemand(
    useFlags: @["ssl", "http2"],
    libc: "musl",
    allocator: "jemalloc",
    targetArch: "x86_64",
    buildFlags: @[]
  )
  
  let v2 = VariantDemand(
    useFlags: @["brotli", "gzip"],
    libc: "musl",
    allocator: "jemalloc",
    targetArch: "x86_64",
    buildFlags: @[]
  )
  
  let result = unifyVariants(@[v1, v2])
  discard result
  
  endOperation(opId)

proc simulateGraphConstruction() =
  ## Simulate dependency graph construction
  
  let opId = startOperation(GraphConstruction, "build-graph")
  
  var graph = DependencyGraph(
    nodes: @[],
    edges: @[]
  )
  
  # Add some nodes
  for i in 0..<50:
    let node = PackageId(
      name: fmt"package-{i}",
      version: "1.0.0",
      variant: "default"
    )
    graph.nodes.add(node)
  
  # Add some edges
  for i in 0..<40:
    let edge = DependencyEdge(
      from: graph.nodes[i],
      to: graph.nodes[i + 1],
      kind: Required
    )
    graph.edges.add(edge)
  
  endOperation(opId)

proc simulateTopologicalSort() =
  ## Simulate topological sort
  
  let opId = startOperation(TopologicalSort, "topo-sort")
  
  var graph = DependencyGraph(
    nodes: @[],
    edges: @[]
  )
  
  # Create a simple chain
  for i in 0..<30:
    let node = PackageId(
      name: fmt"package-{i}",
      version: "1.0.0",
      variant: "default"
    )
    graph.nodes.add(node)
  
  for i in 0..<29:
    let edge = DependencyEdge(
      from: graph.nodes[i],
      to: graph.nodes[i + 1],
      kind: Required
    )
    graph.edges.add(edge)
  
  let sorted = topologicalSort(graph)
  discard sorted
  
  endOperation(opId)

proc simulateConflictDetection() =
  ## Simulate conflict detection
  
  let opId = startOperation(ConflictDetection, "detect-conflicts")
  
  let packages = @[
    PackageId(name: "nginx", version: "1.24.0", variant: "default"),
    PackageId(name: "nginx", version: "1.25.0", variant: "default"),
    PackageId(name: "apache", version: "2.4.0", variant: "default")
  ]
  
  let index = buildPackageIndex(packages)
  let conflicts = detectVersionConflictsFast(index)
  discard conflicts
  
  endOperation(opId)

proc simulateHashCalculation() =
  ## Simulate hash calculations
  
  let opId = startOperation(HashCalculation, "calculate-hashes")
  
  let cache = newHashCache()
  
  for i in 0..<100:
    let hash = cache.getCachedHash(fmt"key-{i}", proc(): string =
      # Simulate expensive hash calculation
      var result = ""
      for j in 0..<1000:
        result.add($j)
      return result
    )
    discard hash
  
  endOperation(opId)

proc simulateBuildSynthesis() =
  ## Simulate build synthesis
  
  let opId = startOperation(BuildSynthesis, "synthesize-build")
  
  let demand = VariantDemand(
    useFlags: @["ssl", "http2", "brotli"],
    libc: "musl",
    allocator: "jemalloc",
    targetArch: "x86_64",
    buildFlags: @["-O2", "-march=native"]
  )
  
  # Simulate build hash calculation
  var components: seq[string] = @[]
  components.add("source-hash")
  components.add(demand.libc)
  components.add(demand.allocator)
  for flag in demand.useFlags:
    components.add(flag)
  
  let buildHash = components.join("|")
  discard buildHash
  
  endOperation(opId)

# ============================================================================
# Main Profiling Example
# ============================================================================

proc main() =
  echo ""
  echo "=" .repeat(80)
  echo "PROFILING RESOLVER OPERATIONS"
  echo "=" .repeat(80)
  echo ""
  
  # Enable profiler
  enableProfiler()
  
  echo "Running resolver operations..."
  echo ""
  
  # Simulate typical resolver workflow
  for iteration in 0..<10:
    echo fmt"Iteration {iteration + 1}/10"
    
    # Variant unification (frequent operation)
    for i in 0..<20:
      simulateVariantUnification()
    
    # Graph construction (moderate frequency)
    for i in 0..<5:
      simulateGraphConstruction()
    
    # Topological sort (moderate frequency)
    for i in 0..<5:
      simulateTopologicalSort()
    
    # Conflict detection (less frequent)
    for i in 0..<3:
      simulateConflictDetection()
    
    # Hash calculation (frequent)
    for i in 0..<10:
      simulateHashCalculation()
    
    # Build synthesis (less frequent)
    for i in 0..<2:
      simulateBuildSynthesis()
  
  # Disable profiler
  disableProfiler()
  
  echo ""
  echo "Profiling complete!"
  echo ""
  
  # Print report
  printReport()
  printOptimizationRecommendations()
  
  # Export to CSV
  exportToCSV("resolver_profiling.csv")
  exportDetailedToCSV("resolver_profiling_detailed.csv")
  
  echo ""
  echo "=" .repeat(80)
  echo "PROFILING COMPLETE"
  echo "=" .repeat(80)
  echo ""
  echo "Results exported to:"
  echo "  - resolver_profiling.csv (summary)"
  echo "  - resolver_profiling_detailed.csv (detailed timings)"
  echo ""

when isMainModule:
  main()
