#!/usr/bin/env nu
# provctl-services.nu - Service management utilities for provctl integration
# Usage: nu scripts/provisioning/provctl-services.nu [command] [args...]
#
# Commands:
#   list [preset]     - List services for a preset
#   deploy [preset]   - Deploy services for a preset via provctl
#   start [service]   - Start a service
#   stop [service]    - Stop a service
#   status [service]  - Check service status
#   validate          - Validate service definitions

def main [command: string = "list", ...args] {
    match $command {
        "list" => {
            list_services ($args | first)
        }
        "deploy" => {
            deploy_services ($args | first)
        }
        "start" => {
            start_service ($args | first)
        }
        "stop" => {
            stop_service ($args | first)
        }
        "status" => {
            check_service_status ($args | first)
        }
        "validate" => {
            validate_services
        }
        _ => {
            print "Unknown command: $command"
            print ""
            print "Available commands:"
            print "  list [preset]     - List services for a preset"
            print "  deploy [preset]   - Deploy services for a preset via provctl"
            print "  start [service]   - Start a service"
            print "  stop [service]    - Stop a service"
            print "  status [service]  - Check service status"
            print "  validate          - Validate service definitions"
        }
    }
}

# List services available for a preset
def list_services [preset: string = "local"] {
    let services = (get_services_for_preset $preset)

    print $"Services for preset: ($preset)"
    print ""

    for service in ($services | from json) {
        print $"  • ($service.name)"
        if ($service.enabled) {
            print $"    Status: enabled"
        } else {
            print $"    Status: disabled"
        }
    }
}

# Deploy services for a preset via provctl
def deploy_services [preset: string = "local"] {
    if (check_provctl_available) == false {
        print "✗ provctl is not available"
        print "Install provctl from: https://github.com/Akasha/provctl"
        return
    }

    let services = (get_services_for_preset $preset | from json)
    mut deployed = []
    mut failed = []

    print $"Deploying services for preset: ($preset)"
    print ""

    for service in $services {
        if ($service.enabled == false) {
            print $"  • ($service.name) - skipped (disabled)"
            continue
        }

        try {
            let config_path = $"configs/provisioning/services/($service.name).toml"

            if not ($config_path | path exists) {
                print $"  ✗ ($service.name) - config not found: ($config_path)"
                $failed = ($failed | append $service.name)
                continue
            }

            # Validate service definition
            try {
                provctl validate --config $config_path
            } catch {
                print $"  ✗ ($service.name) - invalid configuration"
                $failed = ($failed | append $service.name)
                continue
            }

            # Deploy service
            try {
                provctl deploy --config $config_path
                print $"  ✓ ($service.name) - deployed"
                $deployed = ($deployed | append $service.name)
            } catch {
                print $"  ✗ ($service.name) - deployment failed"
                $failed = ($failed | append $service.name)
            }
        } catch {
            print $"  ✗ ($service.name) - error"
            $failed = ($failed | append $service.name)
        }
    }

    print ""
    print $"Deployment summary:"
    print $"  Deployed: ($deployed | length)"
    print $"  Failed: ($failed | length)"

    if ($failed | length) > 0 {
        print ""
        print "Failed services:"
        for svc in $failed {
            print $"  • ($svc)"
        }
    }
}

# Start a service
def start_service [service: string] {
    if ($service == null) {
        print "Please specify a service name"
        return
    }

    if (check_provctl_available) == false {
        print "✗ provctl is not available"
        return
    }

    print $"Starting service: ($service)"
    try {
        provctl start $service
        print $"✓ ($service) started"
    } catch {
        print $"✗ Failed to start ($service)"
    }
}

# Stop a service
def stop_service [service: string] {
    if ($service == null) {
        print "Please specify a service name"
        return
    }

    if (check_provctl_available) == false {
        print "✗ provctl is not available"
        return
    }

    print $"Stopping service: ($service)"
    try {
        provctl stop $service
        print $"✓ ($service) stopped"
    } catch {
        print $"✗ Failed to stop ($service)"
    }
}

# Check service status
def check_service_status [service: string = null] {
    if (check_provctl_available) == false {
        print "✗ provctl is not available"
        return
    }

    if ($service == null) {
        # Show all services
        print "Service status:"
        try {
            provctl status
        } catch {
            print "✗ Failed to get service status"
        }
    } else {
        # Show specific service
        print $"Checking status of: ($service)"
        try {
            provctl status $service
        } catch {
            print $"✗ Failed to get status for ($service)"
        }
    }
}

# Validate all service definitions
def validate_services [] {
    print "Validating service definitions..."
    print ""

    let service_dir = "configs/provisioning/services"
    if not ($service_dir | path exists) {
        print $"✗ Service directory not found: ($service_dir)"
        return
    }

    mut valid = []
    mut invalid = []

    let service_files = (ls $service_dir --full | where name ends-with .toml)

    for file in $service_files {
        let file_name = ($file.name | split row "/" | last)
        try {
            if (check_provctl_available) {
                provctl validate --config $file.name
                print $"  ✓ ($file_name)"
                $valid = ($valid | append $file_name)
            } else {
                # Just check if file is valid TOML
                open $file.name
                print $"  ✓ ($file_name)"
                $valid = ($valid | append $file_name)
            }
        } catch {
            print $"  ✗ ($file_name) - invalid"
            $invalid = ($invalid | append $file_name)
        }
    }

    print ""
    print $"Validation summary:"
    print $"  Valid: ($valid | length)"
    print $"  Invalid: ($invalid | length)"

    if ($invalid | length) > 0 {
        print ""
        print "Invalid services:"
        for svc in $invalid {
            print $"  • ($svc)"
        }
    }
}

# Get services for a preset from installation.toml
def get_services_for_preset [preset: string = "local"]: nothing -> string {
    let config_path = "configs/installation.toml"

    if not ($config_path | path exists) {
        print $"✗ Configuration file not found: ($config_path)"
        return "[]"
    }

    try {
        let config = (open $config_path)

        # Extract services from the preset
        if ($config.preset | get -i $preset | get -i services) != null {
            let services = ($config.preset | get $preset | get services)

            # Convert to array format
            let service_list = [
                {name: "surrealdb", enabled: ($services.surrealdb.enabled?)}
                {name: "nats", enabled: ($services.nats.enabled?)}
                {name: "syntaxis-api", enabled: ($services.syntaxis_api.enabled?)}
                {name: "dashboard", enabled: ($services.dashboard.enabled?)}
            ]

            ($service_list | to json)
        } else {
            print $"✗ Preset not found: ($preset)"
            "[]"
        }
    } catch {
        print $"✗ Error reading configuration: ($config_path)"
        "[]"
    }
}

# Check if provctl is available
def check_provctl_available []: nothing -> bool {
    try {
        which provctl 2>/dev/null | null
        true
    } catch {
        false
    }
}

# Run main if executed directly
if ($nu.invocation-dir == (pwd)) {
    main ...$nu.env.ARGS
}
