## Tests for Quantum-Resistant Cryptographic Transitions
##
## This module tests the algorithm migration framework, backward compatibility,
## algorithm detection, validation, and upgrade procedures.

import unittest, times, tables, options, json
import ../src/nimpak/[types_fixed, crypto_transitions]

suite "Quantum-Resistant Cryptographic Transitions":

  setup:
    let currentDate = dateTime(2025, mJul, 22)
    let legacyAlgorithms = CryptoAlgorithms(
      hashAlgorithm: "BLAKE2b",
      signatureAlgorithm: "Ed25519",
      version: "1.0"
    )
    let quantumAlgorithms = CryptoAlgorithms(
      hashAlgorithm: "SHA3-512",
      signatureAlgorithm: "Dilithium",
      version: "2.0"
    )

  test "Algorithm quantum resistance detection":
    check:
      isQuantumResistant("SHA3-512") == true
      isQuantumResistant("BLAKE3") == true
      isQuantumResistant("Dilithium") == true
      isQuantumResistant("SPHINCS+") == true

      isQuantumResistant("BLAKE2b") == false
      isQuantumResistant("SHA256") == false
      isQuantumResistant("Ed25519") == false
      isQuantumResistant("RSA-4096") == false

  test "CryptoAlgorithms quantum resistance check":
    check:
      isQuantumResistant(quantumAlgorithms) == true
      isQuantumResistant(legacyAlgorithms) == false

  test "Algorithm compatibility information":
    let blake2bCompat = getAlgorithmCompatibility("BLAKE2b")
    check:
      blake2bCompat.isSome
      blake2bCompat.get().quantumResistant == false
      blake2bCompat.get().replacementAlgorithm == "BLAKE3"
      blake2bCompat.get().migrationComplexity == Simple

    let dilithiumCompat = getAlgorithmCompatibility("Dilithium")
    check:
      dilithiumCompat.isSome
      dilithiumCompat.get().quantumResistant == true
      dilithiumCompat.get().replacementAlgorithm == ""

  test "Migration status determination":
    # Test with current date (2025)
    check:
      getMigrationStatus("BLAKE2b", currentDate) == InProgress
      getMigrationStatus("Ed25519", currentDate) == NotStarted
      getMigrationStatus("SHA3-512", currentDate) == Completed
      getMigrationStatus("Dilithium", currentDate) == Completed

    # Test with future date (2035)
    let futureDate = dateTime(2035, mJan, 1)
    check:
      getMigrationStatus("BLAKE2b", futureDate) == Deprecated
      getMigrationStatus("Ed25519", futureDate) == PhaseOut

  test "Algorithm validation":
    let legacyIssues = validateAlgorithmSupport(legacyAlgorithms, currentDate)
    check:
      legacyIssues.len > 0
      legacyIssues.anyIt("migration in progress" in it.toLowerAscii())

    let quantumIssues = validateAlgorithmSupport(quantumAlgorithms, currentDate)
    check:
      quantumIssues.len == 0 or quantumIssues.allIt("info:" in it.toLowerAscii())

  test "Recommended algorithm migration":
    let recommended = getRecommendedAlgorithms(legacyAlgorithms, dateTime(2030, mDec, 31))
    check:
      recommended.hashAlgorithm == "BLAKE3"  # First migration step
      recommended.signatureAlgorithm == "Dilithium"
      recommended.version == "2.0"

    let fullyQuantum = getRecommendedAlgorithms(legacyAlgorithms, dateTime(2035, mDec, 31))
    check:
      fullyQuantum.hashAlgorithm == "SHA3-512"  # Final quantum-resistant step
      fullyQuantum.signatureAlgorithm == "Dilithium"

  test "Quantum-resistant migration":
    var testAlgorithms = legacyAlgorithms
    let migrated = migrateToQuantumResistant(testAlgorithms)

    check:
      migrated == true
      isQuantumResistant(testAlgorithms) == true
      testAlgorithms.version == "2.0"

  test "Migration plan creation":
    let transition = createMigrationPlan(legacyAlgorithms, dateTime(2030, mDec, 31))

    check:
      transition.currentAlgorithms == legacyAlgorithms
      transition.targetAlgorithms.hashAlgorithm != legacyAlgorithms.hashAlgorithm
      transition.targetAlgorithms.signatureAlgorithm != legacyAlgorithms.signatureAlgorithm
      transition.compatibilityMode == true

  test "Transition phase determination":
    check:
      getCurrentTransitionPhase(legacyAlgorithms, currentDate) == DualSupport
      getCurrentTransitionPhase(quantumAlgorithms, currentDate) == PostTransition

  test "Compatibility layer creation":
    let layer = createCompatibilityLayer(
      quantumAlgorithms,
      @[legacyAlgorithms]
    )

    check:
      layer.primaryAlgorithms == quantumAlgorithms
      layer.fallbackAlgorithms.len == 1
      layer.fallbackAlgorithms[0] == legacyAlgorithms
      layer.verificationStrategy == TryPrimaryThenFallback

  test "Compatibility layer validation":
    let goodLayer = createCompatibilityLayer(quantumAlgorithms, @[])
    let goodWarnings = validateCompatibilityLayer(goodLayer)
    check:
      goodWarnings.len == 0

    let deprecatedAlgorithms = CryptoAlgorithms(
      hashAlgorithm: "SHA256",
      signatureAlgorithm: "RSA-4096",
      version: "1.0"
    )
    let badLayer = createCompatibilityLayer(legacyAlgorithms, @[deprecatedAlgorithms])
    let badWarnings = validateCompatibilityLayer(badLayer)
    check:
      badWarnings.len > 0

  test "Package format algorithm upgrades":
    # Test NPK binary package upgrade
    let npkUpgrade = upgradePackageAlgorithms(NpkBinary, legacyAlgorithms)
    check:
      npkUpgrade.isOk
      isQuantumResistant(npkUpgrade.get()) == true

    # Test NPR recipe upgrade
    let nprUpgrade = upgradePackageAlgorithms(NprRecipe, legacyAlgorithms)
    check:
      nprUpgrade.isOk
      nprUpgrade.get().hashAlgorithm == "BLAKE3"
      nprUpgrade.get().signatureAlgorithm == "Dilithium"

    # Test NCA chunk upgrade
    let ncaUpgrade = upgradePackageAlgorithms(NcaChunk, legacyAlgorithms)
    check:
      ncaUpgrade.isOk
      ncaUpgrade.get().hashAlgorithm == "BLAKE3"  # Required for Merkle trees

  test "Transition report generation":
    let testPackages = @[
      legacyAlgorithms,
      quantumAlgorithms,
      CryptoAlgorithms(hashAlgorithm: "BLAKE3", signatureAlgorithm: "Ed25519", version: "1.5")
    ]

    let report = createTransitionReport(testPackages)

    check:
      report.hasKey("summary")
      report["summary"]["total_packages"].getInt() == 3
      report["summary"]["quantum_ready"].getInt() == 1
      report.hasKey("algorithm_usage")
      report.hasKey("migration_status")
      report.hasKey("recommendations")

  test "Default quantum algorithms":
    let defaultAlgos = getDefaultQuantumAlgorithms()
    check:
      isQuantumResistant(defaultAlgos) == true
      defaultAlgos.hashAlgorithm == "SHA3-512"
      defaultAlgos.signatureAlgorithm == "Dilithium"
      defaultAlgos.version == "2.0"

  test "Migration timeline lookup":
    let blake2bTimeline = getTransitionTimelineForAlgorithm("BLAKE2b")
    check:
      blake2bTimeline.isSome
      blake2bTimeline.get().fromAlgorithm == "BLAKE2b"
      blake2bTimeline.get().toAlgorithm == "BLAKE3"

    let unknownTimeline = getTransitionTimelineForAlgorithm("UnknownAlgorithm")
    check:
      unknownTimeline.isNone

  test "Migration effort estimation":
    let simpleEffort = estimateMigrationEffort(legacyAlgorithms, legacyAlgorithms)
    check:
      simpleEffort == Simple

    let moderateEffort = estimateMigrationEffort(legacyAlgorithms, quantumAlgorithms)
    check:
      moderateEffort == Moderate  # Due to Dilithium signature complexity

  test "Algorithm migration timeline constants":
    check:
      QUANTUM_MIGRATION_TIMELINE.hashMigrations.len > 0
      QUANTUM_MIGRATION_TIMELINE.signatureMigrations.len > 0
      QUANTUM_MIGRATION_TIMELINE.targetDate.year == 2030
      QUANTUM_MIGRATION_TIMELINE.backwardCompatible == true

  test "Legacy algorithm migration paths":
    check:
      "BLAKE2b" in LEGACY_ALGORITHM_MIGRATIONS
      "Ed25519" in LEGACY_ALGORITHM_MIGRATIONS
      "SHA256" in LEGACY_ALGORITHM_MIGRATIONS
      "RSA-4096" in LEGACY_ALGORITHM_MIGRATIONS

  test "Quantum-resistant algorithm definitions":
    check:
      "SHA3-512" in QUANTUM_RESISTANT_ALGORITHMS
      "BLAKE3" in QUANTUM_RESISTANT_ALGORITHMS
      "Dilithium" in QUANTUM_RESISTANT_ALGORITHMS
      "SPHINCS+" in QUANTUM_RESISTANT_ALGORITHMS

suite "Algorithm Migration Edge Cases":

  test "Unknown algorithm handling":
    let unknownAlgorithms = CryptoAlgorithms(
      hashAlgorithm: "UnknownHash",
      signatureAlgorithm: "UnknownSig",
      version: "1.0"
    )

    check:
      isQuantumResistant(unknownAlgorithms) == false
      getMigrationStatus("UnknownHash") == NotStarted
      getAlgorithmCompatibility("UnknownHash").isNone

  test "Version compatibility edge cases":
    let mixedVersionAlgorithms = CryptoAlgorithms(
      hashAlgorithm: "SHA3-512",
      signatureAlgorithm: "Dilithium",
      version: "1.0"  # Old version with quantum algorithms
    )

    let issues = validateAlgorithmSupport(mixedVersionAlgorithms)
    check:
      issues.anyIt("version 2.0" in it)

  test "Migration deadline edge cases":
    let pastDate = dateTime(2020, mJan, 1)
    let futureDate = dateTime(2040, mJan, 1)

    check:
      getMigrationStatus("BLAKE2b", pastDate) == NotStarted
      getMigrationStatus("BLAKE2b", futureDate) == Deprecated

  test "Empty package list transition report":
    let emptyReport = createTransitionReport(@[])
    check:
      emptyReport["summary"]["total_packages"].getInt() == 0
      emptyReport["summary"]["quantum_ready_percent"].getInt() == 0

suite "Backward Compatibility Scenarios":

  test "Mixed algorithm environment validation":
    let quantumAlgorithms = getDefaultQuantumAlgorithms()
    let legacyAlgorithms = CryptoAlgorithms(
      hashAlgorithm: "BLAKE2b",
      signatureAlgorithm: "Ed25519",
      version: "1.0"
    )

    let mixedPackages = @[quantumAlgorithms, legacyAlgorithms]
    let report = createTransitionReport(mixedPackages)

    check:
      report["summary"]["quantum_ready_percent"].getInt() == 50
      report["recommendations"].getElems().len > 0

  test "Compatibility layer with multiple fallbacks":
    let primary = getDefaultQuantumAlgorithms()
    let fallback1 = CryptoAlgorithms(
      hashAlgorithm: "BLAKE3",
      signatureAlgorithm: "Ed25519",
      version: "1.5"
    )
    let fallback2 = CryptoAlgorithms(
      hashAlgorithm: "BLAKE2b",
      signatureAlgorithm: "Ed25519",
      version: "1.0"
    )

    let layer = createCompatibilityLayer(primary, @[fallback1, fallback2])
    let warnings = validateCompatibilityLayer(layer)

    check:
      layer.fallbackAlgorithms.len == 2
      warnings.len >= 0  # May have warnings about non-quantum fallbacks

  test "Package format specific upgrade paths":
    let testAlgorithms = CryptoAlgorithms(
      hashAlgorithm: "BLAKE2b",
      signatureAlgorithm: "Ed25519",
      version: "1.0"
    )

    # Test all package formats
    for format in [NprRecipe, NpkBinary, NcaChunk, NssSnapshot, NofOverlay]:
      let upgrade = upgradePackageAlgorithms(format, testAlgorithms)
      check:
        upgrade.isOk
        upgrade.get().version != "1.0"  # Should be upgraded