import std/[unittest, options]
import nip/manifest_parser

suite "NIP Security Manifest Tests":

  test "Parse JSON with Sandbox Config":
    let jsonContent = """
    {
      "name": "secure-app",
      "version": "1.0.0",
      "license": "MIT",
      "sandbox": {
        "level": "strict",
        "linux": {
          "seccomp": "default",
          "capabilities": ["drop:all", "add:net_bind_service"],
          "namespaces": ["net", "ipc"]
        },
        "bsd": {
          "pledge": "stdio inet",
          "unveil": ["/tmp:rw", "/home/user/app:r"]
        }
      }
    }
    """
    
    let manifest = parseManifest(jsonContent, NIP, FormatJSON)
    check manifest.sandbox.isSome
    let sb = manifest.sandbox.get()
    
    check sb.level == SandboxStrict
    
    # Linux
    check sb.seccompProfile == some("default")
    check sb.capabilities.len == 2
    check sb.capabilities[0] == "drop:all"
    check sb.namespaces == @["net", "ipc"]
    
    # BSD
    check sb.pledge == some("stdio inet")
    check sb.unveil.len == 2
    check sb.unveil[0] == "/tmp:rw"

  test "Parse KDL with Sandbox Config":
    let kdlContent = """
    package "secure-app" {
      version "1.0.0"
      license "MIT"
      
      sandbox level="strict" {
        linux seccomp="default" {
          capabilities "drop:all" "add:net_bind_service"
          namespaces "net" "ipc"
        }
        bsd pledge="stdio inet" {
          unveil "/tmp:rw" "/home/user/app:r"
        }
      }
    }
    """
    
    let manifest = parseManifest(kdlContent, NIP, FormatKDL)
    check manifest.sandbox.isSome
    let sb = manifest.sandbox.get()
    
    check sb.level == SandboxStrict
    check sb.seccompProfile == some("default")
    check sb.pledge == some("stdio inet")
    check sb.unveil.len == 2

  test "Serialization Roundtrip":
    var manifest = PackageManifest(
      format: NIP,
      name: "roundtrip-app",
      version: parseSemanticVersion("1.0.0"),
      license: "MIT"
    )
    
    manifest.sandbox = some(SandboxConfig(
      level: SandboxStandard,
      seccompProfile: some("strict"),
      capabilities: @["drop:all"],
      pledge: some("stdio rpath")
    ))
    
    # JSON
    let jsonStr = serializeManifestToJSON(manifest)
    let jsonManifest = parseManifest(jsonStr, NIP, FormatJSON)
    check jsonManifest.sandbox.get().level == SandboxStandard
    check jsonManifest.sandbox.get().pledge == some("stdio rpath")
    
    # KDL
    let kdlStr = serializeManifestToKDL(manifest)
    let kdlManifest = parseManifest(kdlStr, NIP, FormatKDL)
    check kdlManifest.sandbox.get().level == SandboxStandard
    check kdlManifest.sandbox.get().seccompProfile == some("strict")

  test "Hash Determinism":
    var m1 = PackageManifest(name: "app", version: parseSemanticVersion("1.0.0"), license: "MIT")
    m1.sandbox = some(SandboxConfig(
      level: SandboxStrict,
      capabilities: @["b", "a"] # Unsorted
    ))
    
    var m2 = PackageManifest(name: "app", version: parseSemanticVersion("1.0.0"), license: "MIT")
    m2.sandbox = some(SandboxConfig(
      level: SandboxStrict,
      capabilities: @["a", "b"] # Sorted
    ))
    
    check calculateManifestHash(m1) == calculateManifestHash(m2)
