## tests/test_database.nim
## Unit tests for the package database system
##
## Tests package storage, retrieval, dependency resolution,
## and all database functionality.

import std/[unittest, os, times, json, tables]
import ../src/nimpak/database

suite "Package Database Tests":

  setup:
    # Create temporary test directory
    let testDir = getTempDir() / "nip_test_db"
    createDir(testDir)

  teardown:
    # Clean up test directory
    let testDir = getTempDir() / "nip_test_db"
    if dirExists(testDir):
      removeDir(testDir)

  test "Database initialization":
    let db = newPackageDatabase()
    db.initDatabase()

    # Check that default packages are loaded
    check db.packages.hasKey("htop")
    check db.packages.hasKey("vim")
    check "htop" in db.packages
    check "vim" in db.packages
    check "curl" in db.packages

  test "Package retrieval":
    let db = newPackageDatabase()
    db.initDatabase()

    let htop = db.getPackage("htop")
    check htop.name == "htop"
    check htop.version == "3.2.2"
    check htop.stream == "stable"
    check htop.size > 0
    check htop.dependencies.len > 0

  test "Package installation tracking":
    let installTestDir = getTempDir() / "nip_test_db_install"
    # Clean up any existing database files
    if dirExists(installTestDir):
      removeDir(installTestDir)
    createDir(installTestDir)

    let db = newPackageDatabase(installTestDir)
    db.initDatabase()

    # Initially not installed
    check db.isInstalled("htop") == false

    # Install package
    let success = db.installPackage("htop")
    check success == true

    # Now should be installed
    check db.isInstalled("htop") == true

  test "Package removal":
    let removeTestDir = getTempDir() / "nip_test_db_remove"
    let db = newPackageDatabase(removeTestDir)
    db.initDatabase()

    # Install then remove
    discard db.installPackage("vim")
    check db.isInstalled("vim") == true

    let success = db.removePackage("vim")
    check success == true
    check db.isInstalled("vim") == false

  test "Dependency resolution":
    let db = newPackageDatabase()
    db.initDatabase()

    let htop = db.getPackage("htop")
    check "ncurses" in htop.dependencies

    # Installing htop should also install dependencies
    discard db.installPackage("htop")
    check db.isInstalled("htop") == true
    check db.isInstalled("ncurses") == true

  test "Package listing":
    let listingTestDir = getTempDir() / "nip_test_db_listing"
    let db = newPackageDatabase(listingTestDir)
    db.initDatabase()

    # Install some packages
    discard db.installPackage("htop")
    discard db.installPackage("vim")

    let installed = db.listInstalled()
    check installed.len >= 2

    var foundHtop = false
    var foundVim = false
    for pkg in installed:
      if pkg.name == "htop": foundHtop = true
      if pkg.name == "vim": foundVim = true

    check foundHtop == true
    check foundVim == true

  test "Package search":
    let db = newPackageDatabase()
    db.initDatabase()

    let results = db.searchPackages("editor")
    check results.len > 0

    # Should find vim (which has "editor" in description)
    var foundVim = false
    for pkg in results:
      if pkg.name == "vim": foundVim = true
    check foundVim == true

  test "Total installed size calculation":
    let db = newPackageDatabase()
    db.initDatabase()

    # Install some packages
    discard db.installPackage("htop")
    discard db.installPackage("vim")

    let totalSize = db.getTotalInstalledSize()
    check totalSize > 0

  test "Package metadata":
    let db = newPackageDatabase()
    db.initDatabase()

    let curl = db.getPackage("curl")
    check curl.name == "curl"
    check curl.description.len > 0
    check curl.tags.len > 0
    check "network" in curl.tags

  test "Package streams":
    let db = newPackageDatabase()
    db.initDatabase()

    # Check that packages have stream information
    let htop = db.getPackage("htop")
    check htop.stream == "stable"

    let vim = db.getPackage("vim")
    check vim.stream.len > 0  # Should have some stream value

  test "Package installation with dependencies":
    let db = newPackageDatabase()
    db.initDatabase()

    # Test complex dependency chain
    let firefox = db.getPackage("firefox")
    check firefox.dependencies.len > 0

    # Installing firefox should install all dependencies
    let success = db.installPackage("firefox")
    check success == true

    # Check that dependencies are installed
    for dep in firefox.dependencies:
      if dep in db.packages:
        check db.isInstalled(dep) == true

suite "Database Performance Tests":

  test "Large package database performance":
    let db = newPackageDatabase()
    db.initDatabase()

    # Test that we can handle the full package database
    # Test that we can handle the full package database
    # Check that we have several packages loaded
    check db.packages.hasKey("htop")
    check db.packages.hasKey("vim")
    check db.packages.hasKey("git")
    check db.packages.hasKey("firefox")

    # Test search performance
    let startTime = cpuTime()
    let results = db.searchPackages("test")
    let endTime = cpuTime()

    # Search should be fast (under 1 second for test database)
    check (endTime - startTime) < 1.0

  test "Installation performance":
    let db = newPackageDatabase()
    db.initDatabase()

    # Test installation speed
    let startTime = cpuTime()
    discard db.installPackage("htop")
    let endTime = cpuTime()

    # Installation should be fast
    check (endTime - startTime) < 1.0

  test "Database persistence":
    let testDbPath = getTempDir() / "nip_test_db" / "test.db"

    # Create database and install packages
    block:
      let db = newPackageDatabase(testDbPath)
      db.initDatabase()
      discard db.installPackage("htop")
      discard db.installPackage("vim")

    # Load database again and check persistence
    block:
      let db2 = newPackageDatabase(testDbPath)
      db2.initDatabase()
      check db2.isInstalled("htop") == true
      check db2.isInstalled("vim") == true

suite "Database Error Handling":

  test "Non-existent package handling":
    let db = newPackageDatabase()
    db.initDatabase()

    # Should handle non-existent packages gracefully
    expect(KeyError):
      discard db.getPackage("nonexistent-package")

    let success = db.installPackage("nonexistent-package")
    check success == false

  test "Double installation handling":
    let db = newPackageDatabase()
    db.initDatabase()

    # Install package twice
    let success1 = db.installPackage("htop")
    let success2 = db.installPackage("htop")

    check success1 == true
    check success2 == true  # Should handle gracefully
    check db.isInstalled("htop") == true

  test "Remove non-installed package":
    let db = newPackageDatabase()
    db.initDatabase()

    # Try to remove package that's not installed
    let success = db.removePackage("definitely-not-installed-package")
    check success == false

when isMainModule:
  echo "🧪 Running Database Tests..."
  echo "Testing package database with dependency resolution..."

  # This will run all the test suites
  discard