## Property-Based Tests for NPK Manifest - TDD Approach
##
## **Feature:** 01-nip-unified-storage-and-formats
## **Property 3:** Manifesttrip
## **Validates:** Requirements 6.4
##
## **Property Statement:**
## For any NPK manifest, parsing and regenerating SHALL produce semantically equivalent KDL
##
## **TDD Strategy:**
## This test is written FIRST to expose gaps in the implementation.
## Test failures will drive the implementation of parseNPKManifest and generateNPKManifest.
## We use a MAXIMALLY POPULATED manifest to ensure ALL fields are tested.

import std/[unittest, times, options, strutils]
import nip/npk_manifest
import nip/manifest_parser

# ============================================================================
# Helper: Create Maximally Populated NPK Manifest
# ============================================================================

proc createFullNPKManifest*(): NPKManifest =
  ## Creates a maximally populated NPKManifest instance for roundtrip testing.
  ## This ensures we test ALL fields, not just the minimal required ones.
  ##
  ## **Philosophy:** Test the hardest case first. If this passes, simpler cases will too.

  result = NPKManifest(
    name: "nexus-base-pkg",
    version: parseSemanticVersion("1.2.3-alpha.1+build.2"),
    buildDate: parse("2025-11-20T14:00:00Z", "yyyy-MM-dd'T'HH:mm:ss'Z'"),

    metadata: PackageInfo(
      description: "Core dependency package for NexusOS.",
      license: "Dual-ACUL-EUPL-1.2",
      homepage: some("https://nexus.os/base"),
      author: some("Markus Maiwald"),
      maintainer: some("team@nexus.os"),
      tags: @["core", "utility", "system"]
    ),

    provenance: ProvenanceInfo(
      source: "https://nexus.os/sources/base-1.2.3.tar.gz",
      sourceHash: "xxh3-source123456789abc",
      upstream: some("https://upstream.project.org"),
      buildTimestamp: parse("2025-11-20T14:00:00Z", "yyyy-MM-dd'T'HH:mm:ss'Z'"),
      builder: some("build-bot@nexus.os")
    ),

    buildConfig: BuildConfiguration(
      configureFlags: @["--prefix=/usr", "--enable-shared"],
      compilerFlags: @["-O3", "-fno-lto", "-march=native"],
      compilerVersion: "gcc-13.2.0",
      targetArchitecture: "x86_64",
      libc: "glibc",
      allocator: "jemalloc",
      buildSystem: "meson"
    ),

    dependencies: @[
      Dependency(
        name: "zlib",
        version: "1.2.13",
        buildHash: "xxh3-zlib-build-hash",
        optional: false
      ),
      Dependency(
        name: "openssl",
        version: "3.0.0",
        buildHash: "xxh3-openssl-build-hash",
        optional: false
      ),
      Dependency(
        name: "gui-tools",
        version: "2.0.0",
        buildHash: "xxh3-gui-build-hash",
        optional: true
      )
    ],

    casChunks: @[
      ChunkReference(
        hash: "xxh3-chunk1-binary",
        size: 1048576,
        chunkType: Binary,
        path: "bin/nexus-base"
      ),
      ChunkReference(
        hash: "xxh3-chunk2-library",
        size: 524288,
        chunkType: Library,
        path: "lib/libnexus.so"
      ),
      ChunkReference(
        hash: "xxh3-chunk3-config",
        size: 4096,
        chunkType: Config,
        path: "etc/nexus.conf"
      )
    ],

    install: InstallPaths(
      programsPath: "/Programs/NexusBase/1.2.3",
      binPath: "/Programs/NexusBase/1.2.3/bin",
      libPath: "/Programs/NexusBase/1.2.3/lib",
      sharePath: "/Programs/NexusBase/1.2.3/share",
      etcPath: "/Programs/NexusBase/1.2.3/etc"
    ),

    system: SystemIntegration(
      services: @[
        ServiceSpec(
          name: "nexus-base",
          serviceType: "systemd",
          enable: true,
          startOnBoot: true
        )
      ],
      users: @[
        UserSpec(
          name: "nexus",
          uid: some(1000),
          system: true,
          shell: "/bin/false",
          home: some("/var/lib/nexus")
        )
      ],
      groups: @[
        GroupSpec(
          name: "nexus",
          gid: some(1000),
          system: true
        )
      ],
      systemPaths: @["/usr/bin/nexus-base"]
    ),

    buildHash: "xxh3-build-config-hash",

    signature: SignatureInfo(
      algorithm: "ed25519",
      keyId: "packager-2024-key",
      signature: "base64-encoded-signature-placeholder"
    )
  )

# ============================================================================
# Property Tests - Written FIRST to Drive Implementation
# ============================================================================

suite "NPK Manifest Roundtrip Property Tests (Task 6.1)":

  test "Property 3: KDL Generation - Verify output structure":
    ## **Phase 1:** Test that generateNPKManifest produces valid KDL
    ## This will fail initially and show us what's missing

    let manifest = createFullNPKManifest()
    let kdl = generateNPKManifest(manifest)

    # Basic sanity checks
    check kdl.len > 0
    check "package" in kdl
    check manifest.name in kdl

    # Print generated KDL for inspection
    echo "\n=== Generated KDL (Phase 1) ===\n"
    echo kdl
    echo "=== End KDL ===\n"

  test "Property 3: Full Roundtrip - ALL FIELDS":
    ## **Phase 2:** Full roundtrip test
    ## This is the MAIN test that will expose all gaps
    ##
    ## **Feature: 01-nip-unified-storage-and-formats, Property 3: Manifest Roundtrip**
    ## **Validates: Requirements 6.4**

    let originalManifest = createFullNPKManifest()

    # Step 1: Generate KDL
    let kdlString = generateNPKManifest(originalManifest)
    check kdlString.len > 0

    # Step 2: Parse KDL back
    let parsedManifest = parseNPKManifest(kdlString)

    # Step 3: Verify ALL fields preserved
    if parsedManifest.name != originalManifest.name:
      echo "Name mismatch: ", parsedManifest.name, " != ", originalManifest.name
    check parsedManifest.name == originalManifest.name

    if parsedManifest.version != originalManifest.version:
      echo "Version mismatch:"
      echo "  Parsed: ", parsedManifest.version
      echo "  Original: ", originalManifest.version
    check parsedManifest.version == originalManifest.version

    if parsedManifest.buildHash != originalManifest.buildHash:
      echo "BuildHash mismatch: ", parsedManifest.buildHash, " != ", originalManifest.buildHash
    check parsedManifest.buildHash == originalManifest.buildHash

    # Step 4: Verify deterministic generation
    let kdlString2 = generateNPKManifest(parsedManifest)
    if kdlString != kdlString2:
      echo "KDL strings don't match!"
      echo "=== Original KDL ==="
      echo kdlString
      echo "=== Regenerated KDL ==="
      echo kdlString2
    check kdlString == kdlString2

suite "NPK Manifest Validation Tests":

  test "Validate manifest with valid xxh3 hashes":
    let validManifest = NPKManifest(
      name: "valid-pkg",
      version: parseSemanticVersion("1.0.0"),
      buildDate: now(),
      metadata: PackageInfo(
        description: "Valid package",
        license: "MIT"
      ),
      provenance: ProvenanceInfo(
        source: "https://example.com/valid.tar.gz",
        sourceHash: "xxh3-valid123",
        buildTimestamp: now()
      ),
      buildConfig: BuildConfiguration(
        compilerVersion: "gcc-13.2.0",
        targetArchitecture: "x86_64",
        libc: "musl",
        allocator: "default",
        buildSystem: "cmake"
      ),
      install: InstallPaths(
        programsPath: "/Programs/Valid/1.0.0",
        binPath: "/Programs/Valid/1.0.0/bin",
        libPath: "/Programs/Valid/1.0.0/lib",
        sharePath: "/Programs/Valid/1.0.0/share",
        etcPath: "/Programs/Valid/1.0.0/etc"
      ),
      system: SystemIntegration(),
      buildHash: "xxh3-build123",
      signature: SignatureInfo(
        algorithm: "ed25519",
        keyId: "test-key",
        signature: "test-signature"
      )
    )

    let issues = validateNPKManifest(validManifest)
    check issues.len == 0
