# CoreDNS Integration Tests
# Comprehensive tests for CoreDNS functionality

use ../lib_provisioning/coredns/corefile.nu *
use ../lib_provisioning/coredns/zones.nu *
use ../lib_provisioning/coredns/service.nu *
use ../lib_provisioning/utils/log.nu *

# Test suite runner
export def main [] {
    print "\nCoreD NS Integration Test Suite\n================================\n"

    let results = [
        (test-corefile-generation)
        (test-zone-file-creation)
        (test-zone-record-management)
        (test-corefile-validation)
        (test-zone-validation)
        (test-dns-config)
    ]

    let total = $results | length
    let passed = $results | where passed == true | length
    let failed = $total - $passed

    print $"\n\nTest Summary\n============"
    print $"Total:  ($total)"
    print $"Passed: ($passed) ✓"
    print $"Failed: ($failed) ($failed | if $in > 0 { '✗' } else { '' })"

    if $failed > 0 {
        print "\n❌ Some tests failed"
        exit 1
    } else {
        print "\n✅ All tests passed!"
    }
}

# Test Corefile generation
def test-corefile-generation [] -> record {
    print "Test: Corefile Generation"

    let test_config = {
        mode: "local"
        local: {
            port: 5353
            zones_path: "/tmp/test-coredns/zones"
            zones: ["test.local", "example.local"]
        }
        upstream: ["8.8.8.8", "1.1.1.1"]
        enable_logging: true
        enable_metrics: true
        metrics_port: 9153
        dynamic_updates: {
            enabled: true
        }
    }

    # Generate and validate corefile (no try-catch)
    let result = (do {
        let corefile = generate-corefile $test_config

        let has_zones = ($corefile | str contains "test.local") and ($corefile | str contains "example.local")
        let has_forward = $corefile | str contains "forward ."
        let has_upstream = ($corefile | str contains "8.8.8.8") and ($corefile | str contains "1.1.1.1")
        let has_metrics = $corefile | str contains "prometheus"

        if $has_zones and $has_forward and $has_upstream and $has_metrics {
            print "  ✓ Corefile generated successfully"
            { test: "corefile_generation", passed: true }
        } else {
            print "  ✗ Corefile missing expected elements"
            { test: "corefile_generation", passed: false, error: "Missing elements" }
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        print $"  ✗ Failed: ($result.stderr)"
        { test: "corefile_generation", passed: false, error: $result.stderr }
    }
}

# Test zone file creation
def test-zone-file-creation [] -> record {
    print "Test: Zone File Creation"

    let test_zone = "test.local"
    let test_zones_path = "/tmp/test-coredns/zones"

    # Create and validate zone file (no try-catch)
    let result = (do {
        mkdir $test_zones_path

        let result = create-zone-file $test_zone $test_zones_path --config {}

        if $result {
            let zone_file = $"($test_zones_path)/($test_zone).zone"

            if ($zone_file | path exists) {
                let content = open $zone_file

                let has_origin = $content | str contains "$ORIGIN"
                let has_soa = $content | str contains "SOA"
                let has_ns = $content | str contains "NS"

                if $has_origin and $has_soa and $has_ns {
                    print "  ✓ Zone file created with required records"

                    rm -rf $test_zones_path

                    { test: "zone_file_creation", passed: true }
                } else {
                    print "  ✗ Zone file missing required records"
                    rm -rf $test_zones_path
                    { test: "zone_file_creation", passed: false, error: "Missing records" }
                }
            } else {
                print "  ✗ Zone file not created"
                { test: "zone_file_creation", passed: false, error: "File not found" }
            }
        } else {
            print "  ✗ create-zone-file returned false"
            { test: "zone_file_creation", passed: false, error: "Function returned false" }
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        print $"  ✗ Failed: ($result.stderr)"
        { test: "zone_file_creation", passed: false, error: $result.stderr }
    }
}

# Test zone record management
def test-zone-record-management [] -> record {
    print "Test: Zone Record Management"

    let test_zone = "test.local"
    let test_zones_path = "/tmp/test-coredns/zones"

    # Manage zone records (no try-catch)
    let result = (do {
        mkdir $test_zones_path
        create-zone-file $test_zone $test_zones_path --config {}

        let add_result = add-a-record $test_zone "server01" "10.0.1.10" --zones-path $test_zones_path

        if not $add_result {
            print "  ✗ Failed to add A record"
            rm -rf $test_zones_path
            return { test: "zone_record_management", passed: false, error: "Failed to add record" }
        }

        let records = list-zone-records $test_zone --zones-path $test_zones_path

        let has_record = $records | any {|r| $r.name == "server01" and $r.value == "10.0.1.10"}

        if not $has_record {
            print "  ✗ Added record not found in zone"
            rm -rf $test_zones_path
            return { test: "zone_record_management", passed: false, error: "Record not found" }
        }

        let remove_result = remove-record $test_zone "server01" --zones-path $test_zones_path

        if not $remove_result {
            print "  ✗ Failed to remove record"
            rm -rf $test_zones_path
            return { test: "zone_record_management", passed: false, error: "Failed to remove" }
        }

        let records_after = list-zone-records $test_zone --zones-path $test_zones_path
        let still_exists = $records_after | any {|r| $r.name == "server01"}

        if $still_exists {
            print "  ✗ Record still exists after removal"
            rm -rf $test_zones_path
            return { test: "zone_record_management", passed: false, error: "Record not removed" }
        }

        print "  ✓ Record management working correctly"

        rm -rf $test_zones_path

        { test: "zone_record_management", passed: true }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        print $"  ✗ Failed: ($result.stderr)"
        rm -rf $test_zones_path
        { test: "zone_record_management", passed: false, error: $result.stderr }
    }
}

# Test Corefile validation
def test-corefile-validation [] -> record {
    print "Test: Corefile Validation"

    let test_dir = "/tmp/test-coredns"

    # Validate Corefile (no try-catch)
    let result = (do {
        mkdir $test_dir

        let valid_corefile = $"($test_dir)/Corefile.valid"
        $"test.local:5353 {
    file /zones/test.local.zone
    log
    errors
}

.:5353 {
    forward . 8.8.8.8
    log
    errors
}" | save -f $valid_corefile

        let validation = validate-corefile $valid_corefile

        if $validation.valid {
            print "  ✓ Valid Corefile validated successfully"
            rm -rf $test_dir
            { test: "corefile_validation", passed: true }
        } else {
            print $"  ✗ Valid Corefile marked as invalid: ($validation.errors)"
            rm -rf $test_dir
            { test: "corefile_validation", passed: false, error: "Validation failed" }
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        print $"  ✗ Failed: ($result.stderr)"
        rm -rf $test_dir
        { test: "corefile_validation", passed: false, error: $result.stderr }
    }
}

# Test zone validation
def test-zone-validation [] -> record {
    print "Test: Zone Validation"

    let test_zone = "test.local"
    let test_zones_path = "/tmp/test-coredns/zones"

    # Validate zone file (no try-catch)
    let result = (do {
        mkdir $test_zones_path
        create-zone-file $test_zone $test_zones_path --config {}

        let validation = validate-zone-file $test_zone --zones-path $test_zones_path

        if $validation.valid {
            print "  ✓ Valid zone file validated successfully"
            rm -rf "/tmp/test-coredns"
            { test: "zone_validation", passed: true }
        } else {
            print $"  ✗ Valid zone marked as invalid: ($validation.errors)"
            rm -rf "/tmp/test-coredns"
            { test: "zone_validation", passed: false, error: "Validation failed" }
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        print $"  ✗ Failed: ($result.stderr)"
        rm -rf "/tmp/test-coredns"
        { test: "zone_validation", passed: false, error: $result.stderr }
    }
}

# Test DNS configuration
def test-dns-config [] -> record {
    print "Test: DNS Configuration"

    # Test DNS configuration (no try-catch)
    let result = (do {
        let test_config = {
            mode: "local"
            local: {
                enabled: true
                deployment_type: "binary"
                port: 5353
                zones: ["test.local"]
            }
            upstream: ["8.8.8.8"]
            default_ttl: 300
        }

        let has_mode = $test_config.mode? != null
        let has_local = $test_config.local? != null
        let has_upstream = $test_config.upstream? != null

        if $has_mode and $has_local and $has_upstream {
            print "  ✓ DNS configuration structure valid"
            { test: "dns_config", passed: true }
        } else {
            print "  ✗ DNS configuration missing required fields"
            { test: "dns_config", passed: false, error: "Missing fields" }
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        print $"  ✗ Failed: ($result.stderr)"
        { test: "dns_config", passed: false, error: $result.stderr }
    }
}

# Individual test runners for selective testing

export def "test corefile" [] {
    test-corefile-generation
}

export def "test zones" [] {
    test-zone-file-creation
    test-zone-record-management
    test-zone-validation
}

export def "test validation" [] {
    test-corefile-validation
    test-zone-validation
}

export def "test config" [] {
    test-dns-config
}
