## Frozen Source Adapter
##
## This module implements the frozen adapter for pre-built binary sources
## like Nix and Arch Linux. Frozen sources provide packages with fixed
## variant profiles - you get what's available or nothing.
##
## Philosophy:
## - Frozen = pre-built binaries with fixed configurations
## - Fast deployment (no build time)
## - Limited flexibility (can't customize variants)
## - Perfect for common use cases
##
## Examples:
## - Nix: Provides binaries for common configurations
## - Arch/AUR: Pre-built packages with standard flags
## - Debian/Ubuntu: Binary packages with fixed options

import std/[options, tables]
import ./source_adapter
import ./variant_types

type
  # Frozen adapter for pre-built binary sources
  FrozenAdapter* = ref object of SourceAdapter
    packages*: Table[string, seq[PackageMetadata]]  ## Available packages by name

# Constructor
proc newFrozenAdapter*(name: string, priority: int = 50): FrozenAdapter =
  ## Create a new frozen adapter
  ## 
  ## Args:
  ##   name: Source name (e.g., "nix", "arch", "debian")
  ##   priority: Selection priority (default: 50)
  
  result = FrozenAdapter(
    name: name,
    class: Frozen,
    priority: priority,
    packages: initTable[string, seq[PackageMetadata]]()
  )

# Add a package to the frozen source
proc addPackage*(adapter: FrozenAdapter, metadata: PackageMetadata) =
  ## Add a package with its available variants to the frozen source
  ## 
  ## This simulates the package database of a frozen source.
  ## In production, this would query the actual source (Nix cache, Arch repos, etc.)
  
  if not adapter.packages.hasKey(metadata.name):
    adapter.packages[metadata.name] = @[]
  
  adapter.packages[metadata.name].add(metadata)

# Check if adapter can satisfy a demand
method canSatisfy*(adapter: FrozenAdapter, demand: VariantDemand): PackageAvailability =
  ## Check if this frozen source can satisfy a variant demand
  ## 
  ## Returns:
  ##   Available: Package exists with exact variant match
  ##   WrongVariant: Package exists but variant doesn't match
  ##   Unavailable: Package doesn't exist in this source
  
  # Check if package exists
  if not adapter.packages.hasKey(demand.packageName):
    return Unavailable
  
  # Check if any available variant matches the demand
  let availablePackages = adapter.packages[demand.packageName]
  
  for pkg in availablePackages:
    # Check each available variant
    for availableVariant in pkg.availableVariants:
      if availableVariant == demand.variantProfile:
        return Available
  
  # Package exists but no matching variant
  return WrongVariant

# Get package metadata for a demand
method getVariant*(adapter: FrozenAdapter, demand: VariantDemand): Option[PackageMetadata] =
  ## Get package metadata for a specific variant demand
  ## 
  ## Returns Some(metadata) if exact variant match found, None otherwise
  
  # Check if package exists
  if not adapter.packages.hasKey(demand.packageName):
    return none(PackageMetadata)
  
  # Find matching variant
  let availablePackages = adapter.packages[demand.packageName]
  
  for pkg in availablePackages:
    for availableVariant in pkg.availableVariants:
      if availableVariant == demand.variantProfile:
        return some(pkg)
  
  # No matching variant found
  return none(PackageMetadata)

# Synthesize is not supported for frozen adapters
method synthesize*(adapter: FrozenAdapter, demand: VariantDemand): Result[CasId, BuildError] =
  ## Frozen adapters cannot build packages - they only provide pre-built binaries
  ## 
  ## This method always returns an error for frozen adapters.
  ## Use flexible adapters if you need to build from source.
  
  return err[CasId, BuildError](BuildError(
    message: "Cannot synthesize packages from frozen source: " & adapter.name,
    exitCode: 1,
    buildLog: "Frozen sources only provide pre-built binaries. Use a flexible source to build from source."
  ))

# Helper to create a simple package metadata
proc newPackageMetadata*(
  name: string,
  version: string,
  variants: seq[VariantProfile],
  dependencies: seq[VariantDemand] = @[],
  sourceHash: string = "",
  buildTime: int = 0
): PackageMetadata =
  ## Create package metadata for a frozen source
  ## 
  ## Args:
  ##   name: Package name
  ##   version: Package version
  ##   variants: Available variant profiles
  ##   dependencies: Package dependencies
  ##   sourceHash: Source hash (optional)
  ##   buildTime: Build time in seconds (0 for frozen)
  
  PackageMetadata(
    name: name,
    version: version,
    availableVariants: variants,
    dependencies: dependencies,
    sourceHash: sourceHash,
    buildTime: buildTime
  )

