#!/usr/bin/env nu
# test-presets.nu - Tests for installation presets
#
# Tests validate that all presets are properly configured and valid

# Test 1: Load configuration file
def test_load_config [] {
    let config = (try {
        open "configs/installation.toml"
    } catch {
        error make { msg: "Failed to load configs/installation.toml" }
    })

    assert ($config | type) == "record"
    print "✓ test_load_config passed"
}

# Test 2: All required presets exist
def test_all_required_presets_exist [] {
    let config = (open "configs/installation.toml")
    let presets = ($config | get preset | keys)

    let required = ["local", "minimal", "dev", "staging", "production", "custom"]

    for required_preset in $required {
        assert ($presets | contains [$required_preset]) $"Missing preset: ($required_preset)"
    }

    print "✓ test_all_required_presets_exist passed"
}

# Test 3: Preset structure validation
def test_preset_structure [] {
    let config = (open "configs/installation.toml")
    let presets = ($config | get preset)

    for preset_name in ($presets | keys) {
        let preset = ($presets | get $preset_name)

        # Required fields
        assert ($preset | has "name") $"Preset ($preset_name) missing 'name'"
        assert ($preset | has "description") $"Preset ($preset_name) missing 'description'"
        assert ($preset | has "database_backend") $"Preset ($preset_name) missing 'database_backend'"

        # Validate types
        assert (($preset.name | type) == "string") $"Preset ($preset_name) 'name' not string"
        assert (($preset.description | type) == "string") $"Preset ($preset_name) 'description' not string"
    }

    print "✓ test_preset_structure passed"
}

# Test 4: Database backend validation
def test_database_backends [] {
    let config = (open "configs/installation.toml")
    let presets = ($config | get preset)

    let valid_backends = ["sqlite", "surrealdb", "none"]

    for preset_name in ($presets | keys) {
        let backend = ($presets | get $preset_name | get database_backend)
        assert ($valid_backends | contains [$backend]) $"Invalid database backend for ($preset_name): ($backend)"
    }

    print "✓ test_database_backends passed"
}

# Test 5: Services configuration for each preset
def test_services_configuration [] {
    let config = (open "configs/installation.toml")
    let presets = ($config | get preset)

    for preset_name in ($presets | keys) {
        let preset = ($presets | get $preset_name)

        if ($preset | has "services") {
            let services = ($preset.services)

            # Each service should be a record with enabled field
            for service_name in ($services | keys) {
                let service = ($services | get $service_name)
                assert ($service | has "enabled") $"Service ($service_name) in preset ($preset_name) missing 'enabled' field"
            }
        }
    }

    print "✓ test_services_configuration passed"
}

# Test 6: provctl configuration
def test_provctl_configuration [] {
    let config = (open "configs/installation.toml")
    let presets = ($config | get preset)

    let valid_modes = ["auto", "required", "disabled"]

    for preset_name in ($presets | keys) {
        let preset = ($presets | get $preset_name)

        if ($preset | has "provctl_required") {
            let required = ($preset.provctl_required)
            assert (($required | type) == "bool") $"provctl_required in ($preset_name) is not bool"
        }

        if ($preset | has "provctl_recommended") {
            let recommended = ($preset.provctl_recommended)
            assert (($recommended | type) == "bool") $"provctl_recommended in ($preset_name) is not bool"
        }
    }

    print "✓ test_provctl_configuration passed"
}

# Test 7: Database configuration exists for each used backend
def test_database_config_completeness [] {
    let config = (open "configs/installation.toml")
    let presets = ($config | get preset)
    let databases = ($config | get database)

    let used_backends = (
        $presets
        | values
        | map { |p| $p.database_backend }
        | unique
        | where { |b| $b != "none" }
    )

    for backend in $used_backends {
        if ($backend == "sqlite") {
            assert ($databases | has "sqlite") "sqlite database config missing"
        } else if ($backend == "surrealdb") {
            # SurrealDB config might be under subkeys
            # Just verify databases exists
            assert ($databases | keys | any { |k| $k | str contains "surrealdb" }) "No surrealdb database config found"
        }
    }

    print "✓ test_database_config_completeness passed"
}

# Test 8: Service definitions file existence
def test_service_definitions_exist [] {
    let required_services = ["surrealdb", "nats", "syntaxis-api"]

    for service in $required_services {
        let config_path = $"configs/provisioning/services/($service).toml"
        assert ($config_path | path exists) $"Service definition missing: ($config_path)"
    }

    print "✓ test_service_definitions_exist passed"
}

# Test 9: Service definitions are valid TOML
def test_service_definitions_valid_toml [] {
    let services = ["surrealdb", "nats", "syntaxis-api"]

    for service in $services {
        let config_path = $"configs/provisioning/services/($service).toml"
        try {
            let _ = (open $config_path)
        } catch { |err|
            error make { msg: $"Invalid TOML in ($config_path): ($err)" }
        }
    }

    print "✓ test_service_definitions_valid_toml passed"
}

# Test 10: Service definitions have required fields
def test_service_definitions_structure [] {
    let services = ["surrealdb", "nats", "syntaxis-api"]

    for service in $services {
        let config_path = $"configs/provisioning/services/($service).toml"
        let config = (open $config_path)

        assert ($config | has "service") $"($service).toml missing 'service' section"
        assert ($config.service | has "name") $"($service).toml service missing 'name'"
        assert ($config.service | has "description") $"($service).toml service missing 'description'"

        # Optional but common fields
        if ($config | has "health_check") {
            assert ($config.health_check | has "type") $"($service).toml health_check missing 'type'"
        }
    }

    print "✓ test_service_definitions_structure passed"
}

# Main test runner
def main [] {
    print ""
    print "Running preset validation tests..."
    print "────────────────────────────────"

    try {
        test_load_config
        test_all_required_presets_exist
        test_preset_structure
        test_database_backends
        test_services_configuration
        test_provctl_configuration
        test_database_config_completeness
        test_service_definitions_exist
        test_service_definitions_valid_toml
        test_service_definitions_structure

        print "────────────────────────────────"
        print "✓ All preset tests passed!"
        print ""
    } catch { |err|
        print ""
        print $"✗ Test failed: ($err)"
        print ""
        exit 1
    }
}

# Helper: Simple assertion
def assert [condition: bool, message: string = "Assertion failed"] {
    if not $condition {
        error make { msg: $message }
    }
}

if ($nu.invocation-dir == (pwd)) {
    main
}
