import std/[times, json, hashes]


# #############################################################################
# Core Type Primitives
# #############################################################################

type
  Blake2bHash* = distinct string # Enforce type safety for BLAKE2b-512 hashes
  Multihash* = distinct string   # For future-proofing hash algorithms (will support BLAKE3 later)
  SemVer* = distinct string      # Semantic Version string

proc `==`*(a, b: SemVer): bool =
  string(a) == string(b)

proc `==`*(a, b: Multihash): bool =
  string(a) == string(b)

proc `==`*(a, b: Blake2bHash): bool =
  string(a) == string(b)

# #############################################################################
# .npk Manifest Types
# #############################################################################

type
  NpkSource* = object
    originPackage*: string
    originVersion*: string

  NpkDependency* = object
    name*: string
    hash*: Blake2bHash

  NpkBuild* = object
    timestamp*: Time
    buildSystem*: string
    compiler*: string
    envHash*: Blake2bHash

  NpkFile* = object
    path*: string
    hash*: Blake2bHash
    permissions*: string

  NpkArtifact* = object
    name*: string
    hash*: Blake2bHash

  NpkService* = object
    serviceType*: string # e.g., "systemd"
    name*: string
    hash*: Blake2bHash

  NpkSignature* = object
    keyType*: string # e.g., "ed25519"
    keyId*: string
    value*: string

  NpkManifest* = object
    name*: string
    version*: SemVer
    description*: string
    channels*: seq[string]
    source*: NpkSource
    dependencies*: seq[NpkDependency]
    build*: NpkBuild
    files*: seq[NpkFile]
    artifacts*: seq[NpkArtifact]
    services*: seq[NpkService]
    signatures*: seq[NpkSignature]

# #############################################################################
# nip.lock (System Generation) Types
# #############################################################################

type
  LockfileGeneration* = object
    id*: Blake2bHash
    created*: Time
    previous*: Blake2bHash

  LockfilePackage* = object
    name*: string
    hash*: Blake2bHash

  NipLock* = object
    lockfileVersion*: string
    generation*: LockfileGeneration
    packages*: seq[LockfilePackage]

# #############################################################################
# Package Management Types
# #############################################################################

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

  SourceMethod* = enum
    Git, Http, Local, Grafted

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

  LibcType* = enum
    Musl, Glibc, None

  AllocatorType* = enum
    Jemalloc, Tcmalloc, Default

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

  Source* = object
    url*: string
    hash*: string
    hashAlgorithm*: string
    sourceMethod*: SourceMethod
    timestamp*: DateTime

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

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

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

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

# #############################################################################
# Error Types
# #############################################################################

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

  ErrorCode* = enum
    # Package errors
    PackageNotFound, DependencyConflict, ChecksumMismatch,
    InvalidMetadata, PackageCorrupted, VersionMismatch,
    # Permission errors
    PermissionDenied, ElevationRequired, ReadOnlyViolation,
    # Network errors  
    NetworkError, DownloadFailed, RepositoryUnavailable, TimeoutError,
    # Build errors
    BuildFailed, CompilationError, MissingDependency,
    # ACUL/Policy errors
    AculViolation, PolicyViolation, SignatureInvalid, TrustViolation,
    # Storage errors
    CellNotFound, ObjectNotFound, FileReadError, FileWriteError,
    StorageFull, QuotaExceeded,
    # Transaction errors
    TransactionFailed, RollbackFailed, LockConflict,
    # GC errors
    GarbageCollectionFailed, ReferenceIntegrityError,
    # Format errors
    InvalidFormat, UnsupportedVersion, MigrationRequired,
    # Generic errors
    InvalidOperation, ConfigurationError, UnknownError

# #############################################################################
# Transaction Types
# #############################################################################

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]

# #############################################################################
# Filesystem Types
# #############################################################################

type
  FilesystemManager* = object
    programsRoot*: string
    indexRoot*: string

  InstallLocation* = object
    programDir*: string
    indexLinks*: seq[SymlinkPair]

  SymlinkPair* = object
    source*: string
    target*: string

# #############################################################################
# Repository Types (NexusForge)
# #############################################################################

type
  RepoType* = enum
    Native, Git, Graft

  GraftBackend* = enum
    Nix, Portage, Pkgsrc, Pacman, Apt, Dnf, Mock

  RepoConfig* = object
    name*: string
    kind*: RepoType
    url*: string
    priority*: int
    # Native specific
    key*: string
    # Git specific
    branch*: string
    token*: string
    # Graft specific
    backend*: GraftBackend

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

proc hash*(pkg: PackageId): Hash =
  hash((pkg.name, pkg.version, pkg.stream))