## Test suite for comprehensive error handling
## Task 37: Implement comprehensive error handling

import unittest, strutils, sequtils
import ../src/nimpak/errors
import ../src/nip/types

suite "Comprehensive Error Handling Tests":

  test "Error formatting":
    let err = packageNotFoundError("nginx")
    let formatted = formatError(err)
    
    check formatted.contains("PackageNotFound")
    check formatted.contains("nginx")
    check formatted.contains("Suggestions")
    check formatted.contains("typos")

  test "Checksum mismatch error":
    let err = checksumMismatchError(
      "/var/cache/nip/pkg.tar",
      "abc123def456",
      "xyz789ghi012"
    )
    
    check err.code == ChecksumMismatch
    check err.msg.contains("Checksum verification failed")
    check err.context.contains("abc123")
    check err.suggestions.len > 0

  test "Permission denied error":
    let err = permissionDeniedError("/usr/lib/nip", "write")
    
    check err.code == PermissionDenied
    check err.msg.contains("write")
    check err.suggestions.len >= 2

  test "Network error handling":
    let err = networkError("https://repo.nexusos.io/index", "Connection refused")
    
    check err.code == NetworkError
    check err.context.contains("Connection refused")

  test "Download failed with HTTP code":
    let err = downloadFailedError("https://repo.nexusos.io/pkg.tar", 404)
    
    check err.code == DownloadFailed
    check err.context.contains("404")

  test "Elevation required error":
    let err = elevationRequiredError("system package installation")
    
    check err.code == ElevationRequired
    check err.msg.contains("Elevated privileges")
    check err.suggestions.anyIt(it.contains("sudo"))

  test "Signature invalid error":
    let err = signatureInvalidError("compromised-pkg", "0xDEADBEEF")
    
    check err.code == SignatureInvalid
    check err.context.contains("0xDEADBEEF")

  test "GC failed error":
    let err = gcFailedError("Objects in use")
    
    check err.code == GarbageCollectionFailed
    check err.suggestions.anyIt(it.contains("gc"))

  test "Reference integrity error":
    let err = referenceIntegrityError("xxh3-abc123def456", 5, 3)
    
    check err.code == ReferenceIntegrityError
    check err.context.contains("Expected: 5")
    check err.context.contains("Actual: 3")

  test "Transaction failed error":
    let err = transactionFailedError("tx-12345", "file_copy")
    
    check err.code == TransactionFailed
    check err.msg.contains("tx-12345")

  test "Error recoverability check":
    let networkErr = networkError("http://example.com", "timeout")
    let sigErr = signatureInvalidError("bad-pkg")
    
    check isRecoverable(networkErr)
    check not isRecoverable(sigErr)

  test "Recovery strategy suggestion":
    let networkErr = networkError("http://example.com", "timeout")
    let permErr = permissionDeniedError("/root", "read")
    let sigErr = signatureInvalidError("bad-pkg")
    
    check suggestRecovery(networkErr) == Retry
    check suggestRecovery(permErr) == Manual
    check suggestRecovery(sigErr) == Abort

  test "Error wrapping":
    let originalErr = networkError("http://repo.io", "DNS failure")
    let wrappedErr = wrapError(originalErr, DownloadFailed, "Package download failed")
    
    check wrappedErr.code == DownloadFailed
    # wrapError puts "Caused by: <original msg>" in context
    check wrappedErr.context.contains("Caused by")
    check wrappedErr.context.contains("http://repo.io")

  test "Error chaining":
    let err1 = networkError("http://repo.io", "timeout")
    let err2 = downloadFailedError("http://repo.io/pkg.tar")
    let err3 = packageNotFoundError("nginx")
    
    let chainedMsg = chain(err1, err2, err3)
    
    check chainedMsg.contains("Error chain")
    check chainedMsg.contains("NetworkError")
    check chainedMsg.contains("DownloadFailed")
    check chainedMsg.contains("PackageNotFound")

  test "All error codes have factory functions coverage":
    # Verify key error codes have dedicated factory functions
    let errors = @[
      packageNotFoundError("test"),
      checksumMismatchError("file", "a", "b"),
      permissionDeniedError("/path", "op"),
      elevationRequiredError("op"),
      networkError("url", "detail"),
      downloadFailedError("url"),
      repositoryUnavailableError("repo"),
      timeoutError("op", 30),
      buildFailedError("pkg", "stage"),
      missingDependencyError("pkg", "dep"),
      signatureInvalidError("pkg"),
      objectNotFoundError("hash"),
      gcFailedError("reason"),
      transactionFailedError("tx", "op"),
      rollbackFailedError("tx", "reason")
    ]
    
    check errors.len >= 15
    for err in errors:
      check err.msg.len > 0
      check err.suggestions.len > 0
