## Unified Storage Architecture for NexusOS
##
## This module implements the unified storage system that supports all three
## package formats (.npk, .nip, .nexter) with shared Content-Addressable Storage (CAS).
##
## Storage Layout:
##   --system level:
##   /var/lib/nexus
##    OR
##   --user level:
##   ~/.local/share/nexus/
##   ├── cas/                    # Shared CAS (chmod 555)
##   │   ├── chunks/            # Compressed chunks
##   │   ├── refs/              # Reference tracking
##   │   │   ├── npks/         # .npk references
##   │   │   ├── nips/         # .nip references
##   │   │   └── nexters/      # .nexter references
##   │   └── audit.log         # Write operation log
##   ├── npks/                  # System packages
##   ├── nips/                  # User applications
##   └── nexters/               # Containers

import std/[os, times, strutils, tables]

type
  StorageRoot* = object
    ## Root directory for unified storage
    basePath*: string
    casPath*: string
    npksPath*: string
    nipsPath*: string
    nextersPath*: string
    auditLogPath*: string

  ChunkType* = enum
    ## Type of chunk stored in CAS
    Binary, Library, Runtime, Config, Data, Base, Tools

  ChunkMetadata* = object
    ## Metadata for a CAS chunk
    hash*: string              # xxh3-128 hash
    size*: int64
    refCount*: int             # Total references across all formats
    compression*: string       # "zstd"
    created*: DateTime
    chunkType*: ChunkType

  FormatType* = enum
    ## Package format type
    NPK, NIP, NEXTER

  CASStore* = object
    ## Content-Addressable Storage manager
    rootPath*: string          # ~/.local/share/nexus/cas
    chunksPath*: string        # cas/chunks/
    refsPath*: string          # cas/refs/
    auditLog*: string          # cas/audit.log
    index*: Table[string, ChunkMetadata]

  CASError* = object of CatchableError
    ## CAS-specific errors
    code*: CASErrorCode
    context*: string

  CASErrorCode* = enum
    CASChunkNotFound,
    CASChunkHashMismatch,
    CASStorageFull,
    CASPermissionDenied,
    CASInvalidHash

const
  DefaultStorageRoot* = "~/.local/share/nexus"
  CASPermissions* = {fpUserRead, fpUserExec, fpGroupRead, fpGroupExec, fpOthersRead, fpOthersExec}  # 555
  WritePermissions* = {fpUserRead, fpUserWrite, fpUserExec, fpGroupRead, fpGroupExec, fpOthersRead, fpOthersExec}  # 755

proc expandPath(path: string): string =
  ## Expand ~ to home directory
  if path.startsWith("~"):
    result = getHomeDir() / path[2..^1]
  else:
    result = path

proc initStorageRoot*(basePath: string = DefaultStorageRoot): StorageRoot =
  ## Initialize the unified storage root structure
  let expandedBase = expandPath(basePath)

  result = StorageRoot(
    basePath: expandedBase,
    casPath: expandedBase / "cas",
    npksPath: expandedBase / "npks",
    nipsPath: expandedBase / "nips",
    nextersPath: expandedBase / "nexters",
    auditLogPath: expandedBase / "cas" / "audit.log"
  )

proc createStorageStructure*(root: StorageRoot): bool =
  ## Create the unified storage directory structure
  ## Returns true if successful, false otherwise
  try:
    # Create base directory
    createDir(root.basePath)

    # Create CAS structure
    createDir(root.casPath)
    createDir(root.casPath / "chunks")
    createDir(root.casPath / "refs")
    createDir(root.casPath / "refs" / "npks")
    createDir(root.casPath / "refs" / "nips")
    createDir(root.casPath / "refs" / "nexters")

    # Create format-specific directories
    createDir(root.npksPath)
    createDir(root.nipsPath)
    createDir(root.nextersPath)

    # Create audit log file
    if not fileExists(root.auditLogPath):
      writeFile(root.auditLogPath, "# NexusOS Unified Storage Audit Log\n")
      writeFile(root.auditLogPath, "# Created: " & $now() & "\n\n")

    # Set CAS to read-only (555)
    setFilePermissions(root.casPath, CASPermissions)

    result = true
  except OSError as e:
    echo "Error creating storage structure: ", e.msg
    result = false
  except IOError as e:
    echo "Error creating audit log: ", e.msg
    result = false

proc verifyStorageStructure*(root: StorageRoot): bool =
  ## Verify that the storage structure exists and is valid
  result = dirExists(root.basePath) and
           dirExists(root.casPath) and
           dirExists(root.casPath / "chunks") and
           dirExists(root.casPath / "refs") and
           dirExists(root.casPath / "refs" / "npks") and
           dirExists(root.casPath / "refs" / "nips") and
           dirExists(root.casPath / "refs" / "nexters") and
           dirExists(root.npksPath) and
           dirExists(root.nipsPath) and
           dirExists(root.nextersPath) and
           fileExists(root.auditLogPath)

proc initCASStore*(rootPath: string): CASStore =
  ## Initialize a CAS store instance
  let expandedRoot = expandPath(rootPath)

  result = CASStore(
    rootPath: expandedRoot,
    chunksPath: expandedRoot / "chunks",
    refsPath: expandedRoot / "refs",
    auditLog: expandedRoot / "audit.log",
    index: initTable[string, ChunkMetadata]()
  )

proc logAuditEntry*(store: CASStore, operation: string, details: string) =
  ## Log an operation to the audit log
  let timestamp = now()
  let entry = "[$#] $#: $#\n" % [$timestamp, operation, details]

  try:
    # Temporarily enable write access
    setFilePermissions(store.rootPath, WritePermissions)

    # Append to audit log
    let f = open(store.auditLog, fmAppend)
    f.write(entry)
    f.close()

    # Restore read-only permissions
    setFilePermissions(store.rootPath, CASPermissions)
  except:
    echo "Warning: Failed to write audit log entry"

when isMainModule:
  echo "Testing Unified Storage Structure..."

  # Test storage initialization
  let root = initStorageRoot()
  echo "Storage root: ", root.basePath
  echo "CAS path: ", root.casPath

  # Create structure
  if createStorageStructure(root):
    echo "✓ Storage structure created successfully"
  else:
    echo "✗ Failed to create storage structure"

  # Verify structure
  if verifyStorageStructure(root):
    echo "✓ Storage structure verified"
  else:
    echo "✗ Storage structure verification failed"

  # Test CAS store
  let store = initCASStore(root.casPath)
  echo "CAS store initialized: ", store.rootPath

  # Test audit logging
  store.logAuditEntry("TEST", "Testing audit log functionality")
  echo "✓ Audit log entry written"
