## NimPak Core Types
##
## This module defines the foundational data structures for the NimPak package
## management system, following NexusOS architectural principles.

import std/[times, tables, options, json]

# =============================================================================
# Result Type for Error Handling
# =============================================================================

type
  Result*[T, E] = object
    case isOk*: bool
    of true:
      okValue*: T
    of false:
      errValue*: E

  VoidResult*[E] = object
    case isOk*: bool
    of true:
      discard
    of false:
      errValue*: E

proc ok*[T, E](val: T): Result[T, E] =
  Result[T, E](isOk: true, okValue: val)

proc ok*[E](ErrorType: typedesc[E]): VoidResult[E] =
  VoidResult[E](isOk: true)

proc err*[T, E](errVal: E): Result[T, E] =
  Result[T, E](isOk: false, errValue: errVal)

proc err*[E](errVal: E): VoidResult[E] =
  VoidResult[E](isOk: false, errValue: errVal)

proc isOk*[T, E](r: Result[T, E]): bool = r.isOk
proc isErr*[T, E](r: Result[T, E]): bool = not r.isOk
proc isOk*[E](r: VoidResult[E]): bool = r.isOk
proc isErr*[E](r: VoidResult[E]): bool = not r.isOk

proc get*[T, E](r: Result[T, E]): T =
  case r.isOk
  of true:
    r.okValue
  of false:
    raise newException(ValueError, "Attempted to get value from error result")

proc getError*[T, E](r: Result[T, E]): E =
  case r.isOk
  of false:
    r.errValue
  of true:
    raise newException(ValueError, "Attempted to get error from ok result")

proc getError*[E](r: VoidResult[E]): E =
  case r.isOk
  of false:
    r.errValue
  of true:
    raise newException(ValueError, "Attempted to get error from ok result")

proc error*[T, E](r: Result[T, E]): E =
  ## Alias for getError for convenience
  r.getError()

proc error*[E](r: VoidResult[E]): E =
  ## Alias for getError for convenience
  r.getError()

# =============================================================================
# Core Error Types
# =============================================================================

type
  NimPakError* = object of CatchableError
    code*: ErrorCode
    context*: string
    suggestions*: seq[string]

  ErrorCode* = enum
    PackageNotFound, DependencyConflict, ChecksumMismatch,
    PermissionDenied, NetworkError, BuildFailed,
    InvalidMetadata, AculViolation, CellNotFound,
    FilesystemError, CasError, GraftError,
    # CAS-specific errors
    ObjectNotFound, CorruptedObject, StorageError, CompressionError,
    FileReadError, FileWriteError, UnknownError

# =============================================================================
# Package Identification and Streams
# =============================================================================

type
  PackageStream* = enum
    Stable, Testing, Dev, LTS, Custom

  PackageId* = object
    name*: string
    version*: string
    stream*: PackageStream

proc `$`*(id: PackageId): string =
  result = id.name & "-" & id.version & "[" & $id.stream & "]"

proc `==`*(a, b: PackageId): bool =
  a.name == b.name and a.version == b.version and a.stream == b.stream

# =============================================================================
# Source and Build Information
# =============================================================================

type
  SourceMethod* = enum
    Git, Http, Local, Grafted

  Source* = object
    url*: string
    hash*: string          # BLAKE2b hash, will support BLAKE3 later
    hashAlgorithm*: string # "blake2b", "blake3", etc.
    sourceMethod*: SourceMethod
    timestamp*: times.DateTime

  BuildSystemType* = enum
    CMake, Meson, Autotools, Cargo, NimBuild, Custom

# =============================================================================
# Runtime and System Configuration
# =============================================================================

type
  LibcType* = enum
    Musl, Glibc, None

  AllocatorType* = enum
    Jemalloc, Internal, GlibcMalloc, System

  RuntimeProfile* = object
    libc*: LibcType
    allocator*: AllocatorType
    systemdAware*: bool
    reproducible*: bool
    tags*: seq[string]

# =============================================================================
# ACUL Compliance
# =============================================================================

type
  AculCompliance* = object
    required*: bool
    membership*: string
    attribution*: string
    buildLog*: string

# =============================================================================
# Package Metadata
# = =============================================================================

type
  PackageMetadata* = object
    description*: string
    license*: string
    maintainer*: string
    tags*: seq[string]
    runtime*: RuntimeProfile

# =============================================================================
# Fragment (Package Definition)
# =============================================================================

type
  Fragment* = object
    id*: PackageId
    source*: Source
    dependencies*: seq[PackageId]
    buildSystem*: BuildSystemType
    metadata*: PackageMetadata
    acul*: AculCompliance

# =============================================================================
# Multi-Variant OS Support
# =============================================================================

type
  OSVariant* = enum
    NexusOS, NexusBSD, NexusSafeCore, NexusUnikernel

  KernelType* = enum
    Linux, DragonflyBSD, Redox, Theseus, Unikernel

  UserspaceType* = enum
    GnuFree, Minimal, NimOnly, Custom

  LicenseModel* = enum
    MitAcul, BsdAcul, ApacheMit, EmbeddedAcul

  VariantConfig* = object
    variant*: OSVariant
    kernel*: KernelType
    libc*: LibcType
    userspace*: UserspaceType
    licenseModel*: LicenseModel

  SystemDefinition* = object
    variant*: VariantConfig
    packages*: seq[PackageId]
    configuration*: JsonNode # System-specific configuration
    immutable*: bool

# =============================================================================
# Content-Addressable Storage (CAS)
# =============================================================================

type
  CasObject* = object
    hash*: string # Multihash (BLAKE2b-512 by default)
    size*: int64
    compressed*: bool

  CasStats* = object
    objectCount*: int
    totalSize*: int64
    compressionRatio*: float

  CasErrorKind* = enum
    ObjectNotFound, CorruptedObject, StorageError, CompressionError

# =============================================================================
# Package Files and Manifests
# =============================================================================

type
  FilePermissions* = object
    mode*: int
    owner*: string
    group*: string

  ChunkRef* = object
    hash*: string
    offset*: int64
    size*: int

  PackageFile* = object
    path*: string
    hash*: string
    hashAlgorithm*: string # "blake2b", "blake3", etc.
    permissions*: FilePermissions
    chunks*: Option[seq[ChunkRef]] # For large files with chunk-level deduplication

  PackageManifest* = object
    files*: seq[PackageFile]
    totalSize*: int64
    created*: times.DateTime
    merkleRoot*: string # Root hash of the entire package content

# =============================================================================
# NPK Package Format
# =============================================================================

type
  Signature* = object
    keyId*: string
    algorithm*: string
    signature*: seq[byte]

  NpkPackage* = object
    metadata*: Fragment
    files*: seq[PackageFile]
    manifest*: PackageManifest
    signature*: Option[Signature]

# =============================================================================
# Grafting and External Sources
# =============================================================================

type
  GraftSource* = enum
    Pacman, Nix, Flatpak

  GraftAuditLog* = object
    timestamp*: times.DateTime
    source*: GraftSource
    packageName*: string
    version*: string
    downloadedFilename*: string
    archiveHash*: string         # BLAKE2b hash of original archive
    hashAlgorithm*: string       # "blake2b" for integrity verification
    sourceOutput*: string        # Captured command output
    downloadUrl*: Option[string] # If determinable
    originalSize*: int64
    deduplicationStatus*: string # "New" or "Reused"

  GraftResult* = object
    fragment*: Fragment
    extractedPath*: string
    originalMetadata*: JsonNode
    auditLog*: GraftAuditLog

# =============================================================================
# System Layers and Runtime Control
# =============================================================================

type
  SystemLayer* = enum
    CoreBase, AppLayer, DesktopLayer, SystemdLayer

  LayerConfig* = object
    layer*: SystemLayer
    libc*: LibcType
    allocator*: AllocatorType
    purpose*: string
    packages*: seq[PackageId]

  CompatibilityRule* = object
    allowed*: bool
    requirements*: seq[string]
    warnings*: seq[string]

# =============================================================================
# NipCells (Per-User Environments)
# =============================================================================

type
  NexusCell* = object
    name*: string
    owner*: string
    programsDir*: string # ~/.nexus/cells/name/Programs
    indexDir*: string    # ~/.nexus/cells/name/Index
    active*: bool

# =============================================================================
# Filesystem Management
# =============================================================================

type
  SymlinkPair* = object
    source*: string # /Programs/App/Version/bin/app
    target*: string # /System/Index/bin/app

  InstallLocation* = object
    programDir*: string # /Programs/App/Version
    indexLinks*: seq[SymlinkPair]

# =============================================================================
# Transaction Management
# =============================================================================

type
  OperationKind* = enum
    CreateDir, CreateFile, CreateSymlink, RemoveFile, RemoveDir

  Operation* = object
    kind*: OperationKind
    target*: string
    data*: JsonNode

  RollbackInfo* = object
    operation*: Operation
    originalState*: JsonNode

  Transaction* = object
    id*: string
    operations*: seq[Operation]
    rollbackData*: seq[RollbackInfo]

# =============================================================================
# Generation Management
# =============================================================================

type
  Generation* = object
    id*: string
    timestamp*: times.DateTime
    packages*: seq[PackageId]
    previous*: Option[string]
    size*: int64

# =============================================================================
# Validation and Security
# =============================================================================

type
  ValidationError* = object
    field*: string
    message*: string
    suggestions*: seq[string]

  SecurityError* = object
    kind*: SecurityErrorKind
    file*: string
    details*: string

  SecurityErrorKind* = enum
    ChecksumMismatch, InvalidSignature, UntrustedKey, CorruptedData
