# CoreDNS CLI Commands
# User-facing commands for DNS management

use ../utils/log.nu *
use ../config/loader.nu get-config
use service.nu *
use zones.nu *
use corefile.nu *

# DNS service status
export def "dns status" [] {
    log info "Checking CoreDNS status"

    let config = get-dns-config
    let status = get-coredns-status --config $config

    print $"
CoreDNS Service Status
======================

Status:          ($status.running | if $in { 'Running ✓' } else { 'Stopped ✗' })
Deployment:      ($status.deployment_type)
Mode:            ($status.mode)
PID:             ($status.pid | default 'N/A')
Healthy:         ($status.healthy | if $in { 'Yes ✓' } else { 'No ✗' })
"

    if $status.running {
        let local_config = $config.local? | default {}
        let port = $local_config.port? | default 5353
        let zones = $local_config.zones? | default []

        print $"
Configuration
-------------
Port:            ($port)
Zones:           ($zones | str join ', ')
"
    }
}

# Start DNS service
export def "dns start" [
    --foreground (-f)    # Run in foreground
    --check              # Check mode
] {
    let config = get-dns-config
    let result = start-coredns $config --foreground=$foreground --check=$check

    if $result {
        print "✓ CoreDNS started successfully"
    } else {
        print "✗ Failed to start CoreDNS"
        exit 1
    }
}

# Stop DNS service
export def "dns stop" [
    --check    # Check mode
] {
    let config = get-dns-config
    let result = stop-coredns --config $config --check=$check

    if $result {
        print "✓ CoreDNS stopped successfully"
    } else {
        print "✗ Failed to stop CoreDNS"
        exit 1
    }
}

# Reload DNS configuration
export def "dns reload" [] {
    let config = get-dns-config
    let result = reload-coredns --config $config

    if $result {
        print "✓ CoreDNS reloaded successfully"
    } else {
        print "✗ Failed to reload CoreDNS"
        exit 1
    }
}

# Restart DNS service
export def "dns restart" [
    --check    # Check mode
] {
    let config = get-dns-config
    let result = restart-coredns $config --check=$check

    if $result {
        print "✓ CoreDNS restarted successfully"
    } else {
        print "✗ Failed to restart CoreDNS"
        exit 1
    }
}

# Install CoreDNS binary
export def "dns install" [
    version?: string = "latest"  # Version to install
    --check
] {
    let result = install-coredns $version --check=$check

    if $result {
        print $"✓ CoreDNS ($version) installed successfully"
    } else {
        print "✗ Failed to install CoreDNS"
        exit 1
    }
}

# Show DNS logs
export def "dns logs" [
    --lines: int = 50    # Number of lines to show
    --follow (-f)        # Follow log output
] {
    show-coredns-logs --lines $lines --follow=$follow
}

# Zone management commands

# List DNS zones
export def "dns zone list" [] {
    let config = get-dns-config
    let local_config = $config.local? | default {}
    let zones = $local_config.zones? | default []
    let zones_path = $local_config.zones_path? | default "~/.provisioning/coredns/zones" | path expand

    print $"
DNS Zones
=========
"

    for zone in $zones {
        let zone_file = $"($zones_path)/($zone).zone"
        let exists = $zone_file | path exists

        print $"  • ($zone) ($exists | if $in { '✓' } else { '✗ (missing)' })"
    }
}

# Show zone details
export def "dns zone show" [
    zone: string    # Zone name
    --format: string = "table"  # Output format: table, json, yaml
] {
    let records = list-zone-records $zone --format $format

    if $format == "table" {
        print $"\nZone: ($zone)\n"
        $records | table
    } else {
        print $records
    }
}

# Create DNS zone
export def "dns zone create" [
    zone: string    # Zone name
    --check
] {
    if $check {
        print $"Check mode: Would create zone ($zone)"
        return
    }

    let config = get-dns-config
    let local_config = $config.local? | default {}
    let zones_path = $local_config.zones_path? | default "~/.provisioning/coredns/zones"

    let result = create-zone-file $zone $zones_path --config $config

    if $result {
        print $"✓ Zone ($zone) created successfully"

        # Update Corefile
        dns config generate
    } else {
        print $"✗ Failed to create zone ($zone)"
        exit 1
    }
}

# Delete DNS zone
export def "dns zone delete" [
    zone: string    # Zone name
    --force         # Skip confirmation
    --check
] {
    if not $force {
        let confirm = input $"Are you sure you want to delete zone ($zone)? (yes/no): "

        if $confirm != "yes" {
            print "Cancelled"
            return
        }
    }

    if $check {
        print $"Check mode: Would delete zone ($zone)"
        return
    }

    let config = get-dns-config
    let local_config = $config.local? | default {}
    let zones_path = $local_config.zones_path? | default "~/.provisioning/coredns/zones" | path expand
    let zone_file = $"($zones_path)/($zone).zone"

    if ($zone_file | path exists) {
        rm $zone_file
        print $"✓ Zone ($zone) deleted successfully"
    } else {
        print $"✗ Zone ($zone) not found"
        exit 1
    }
}

# Record management commands

# Add DNS record
export def "dns record add" [
    name: string            # Record name
    type: string            # Record type (A, AAAA, CNAME, MX, TXT, etc.)
    value: string           # Record value
    --zone: string = "provisioning.local"  # Zone name
    --ttl: int = 300        # TTL in seconds
    --priority: int         # Priority (for MX/SRV)
    --comment: string = ""  # Comment
    --check
] {
    if $check {
        print $"Check mode: Would add record ($name) ($type) ($value) to zone ($zone)"
        return
    }

    let result = match $type {
        "A" => { add-a-record $zone $name $value --ttl $ttl --comment $comment }
        "AAAA" => { add-aaaa-record $zone $name $value --ttl $ttl --comment $comment }
        "CNAME" => { add-cname-record $zone $name $value --ttl $ttl --comment $comment }
        "MX" => {
            if $priority == null {
                print "Error: --priority required for MX records"
                exit 1
            }
            add-mx-record $zone $name $value $priority --ttl $ttl --comment $comment
        }
        "TXT" => { add-txt-record $zone $name $value --ttl $ttl --comment $comment }
        _ => {
            print $"Error: Unsupported record type ($type)"
            exit 1
        }
    }

    if $result {
        print $"✓ Record added: ($name) ($type) ($value)"

        # Reload CoreDNS
        reload-coredns --config (get-dns-config)
    } else {
        print $"✗ Failed to add record"
        exit 1
    }
}

# Remove DNS record
export def "dns record remove" [
    name: string            # Record name
    --zone: string = "provisioning.local"  # Zone name
    --check
] {
    if $check {
        print $"Check mode: Would remove record ($name) from zone ($zone)"
        return
    }

    let result = remove-record $zone $name

    if $result {
        print $"✓ Record removed: ($name)"

        # Reload CoreDNS
        reload-coredns --config (get-dns-config)
    } else {
        print $"✗ Failed to remove record"
        exit 1
    }
}

# List DNS records
export def "dns record list" [
    --zone: string = "provisioning.local"  # Zone name
    --format: string = "table"             # Output format
] {
    let records = list-zone-records $zone --format $format

    if $format == "table" {
        print $"\nDNS Records - Zone: ($zone)\n"
        $records | table
    } else {
        print $records
    }
}

# Update DNS record
export def "dns record update" [
    name: string            # Record name
    type: string            # Record type
    value: string           # New value
    --zone: string = "provisioning.local"  # Zone name
    --ttl: int = 300        # TTL
    --comment: string = ""  # Comment
    --check
] {
    if $check {
        print $"Check mode: Would update record ($name) to ($value) in zone ($zone)"
        return
    }

    # Remove old record
    let remove_result = remove-record $zone $name

    if not $remove_result {
        print $"✗ Failed to remove old record"
        exit 1
    }

    # Add new record
    dns record add $name $type $value --zone $zone --ttl $ttl --comment $comment
}

# Query DNS
export def "dns query" [
    hostname: string        # Hostname to query
    --type: string = "A"    # Record type
    --server: string = "127.0.0.1"  # DNS server
    --port: int = 5353      # DNS port
] {
    log info $"Querying ($hostname) ($type) from ($server):($port)"

    let result = (do {
        dig @$server -p $port $hostname $type
    } | complete)

    if $result.exit_code != 0 {
        print "✗ DNS query failed"
        exit 1
    }
}

# Configuration commands

# Show DNS configuration
export def "dns config show" [] {
    let config = get-dns-config

    print $"
CoreDNS Configuration
=====================
"

    print ($config | to yaml)
}

# Validate DNS configuration
export def "dns config validate" [] {
    let config = get-dns-config
    let local_config = $config.local? | default {}
    let config_path = $local_config.config_path? | default "~/.provisioning/coredns/Corefile" | path expand

    # Validate Corefile
    let corefile_validation = validate-corefile $config_path

    print $"
Corefile Validation
===================

Valid:    ($corefile_validation.valid | if $in { 'Yes ✓' } else { 'No ✗' })
"

    if not ($corefile_validation.errors | is-empty) {
        print "Errors:"
        for error in $corefile_validation.errors {
            print $"  • ($error)"
        }
    }

    if not ($corefile_validation.warnings | is-empty) {
        print "\nWarnings:"
        for warning in $corefile_validation.warnings {
            print $"  • ($warning)"
        }
    }

    # Validate zone files
    let zones = $local_config.zones? | default []

    print $"\n\nZone Files Validation\n=====================\n"

    for zone in $zones {
        let zone_validation = validate-zone-file $zone

        print $"Zone: ($zone)"
        print $"  Valid:    ($zone_validation.valid | if $in { 'Yes ✓' } else { 'No ✗' })"

        if not ($zone_validation.errors | is-empty) {
            print "  Errors:"
            for error in $zone_validation.errors {
                print $"    • ($error)"
            }
        }

        if not ($zone_validation.warnings | is-empty) {
            print "  Warnings:"
            for warning in $zone_validation.warnings {
                print $"    • ($warning)"
            }
        }

        print ""
    }
}

# Generate DNS configuration
export def "dns config generate" [
    --check
] {
    if $check {
        print "Check mode: Would generate DNS configuration"
        return
    }

    let config = get-dns-config
    let local_config = $config.local? | default {}
    let config_path = $local_config.config_path? | default "~/.provisioning/coredns/Corefile" | path expand

    let result = update-corefile $config $config_path

    if $result {
        print $"✓ Corefile generated at ($config_path)"
    } else {
        print "✗ Failed to generate Corefile"
        exit 1
    }
}

# Health check
export def "dns health" [] {
    let config = get-dns-config
    let health = check-coredns-health $config

    if $health {
        print "✓ CoreDNS is healthy"
    } else {
        print "✗ CoreDNS health check failed"
        exit 1
    }
}

# Helper: Get DNS configuration
def get-dns-config [] -> record {
    let full_config = get-config

    # Try to get CoreDNS config from configuration
    let coredns_config = $full_config.coredns? | default {
        mode: "local"
        local: {
            enabled: true
            deployment_type: "binary"
            binary_path: "~/.provisioning/bin/coredns"
            config_path: "~/.provisioning/coredns/Corefile"
            zones_path: "~/.provisioning/coredns/zones"
            port: 5353
            auto_start: true
            zones: ["provisioning.local", "workspace.local"]
        }
        dynamic_updates: {
            enabled: true
            api_endpoint: "http://localhost:8080/dns"
            auto_register_servers: true
        }
        upstream: ["8.8.8.8", "1.1.1.1"]
        default_ttl: 300
        enable_logging: true
        enable_metrics: true
        metrics_port: 9153
    }

    $coredns_config
}
