# Test Environment Management
# Nushell integration for containerized test environments

# Star-import removed (ADR-025 Phase 4). test_environments.nu is test-env code;
# will move to tests/ in a follow-up. If any symbol becomes undefined, the
# fix is an explicit selective import here.

const DEFAULT_ORCHESTRATOR = "http://localhost:8080"

# Detect if orchestrator URL is local (for plugin usage)
def use-local-plugin [orchestrator_url: string] {
    $orchestrator_url == "http://localhost:8080" or
    $orchestrator_url == "http://127.0.0.1:8080" or
    $orchestrator_url == "localhost:8080"
}

# Create test environment
export def "test env create" [
    config: record           # Test environment configuration
    --infra (-i): string     # Infrastructure context
    --auto-start             # Auto-start tests after creation
    --auto-cleanup           # Auto-cleanup after completion
    --orchestrator: string = $DEFAULT_ORCHESTRATOR
] {
    let request = {
        config: $config,
        infra: $infra,
        auto_start: $auto_start,
        auto_cleanup: $auto_cleanup
    }

    let response = (http post $"($orchestrator)/test/environments/create"
        --content-type "application/json"
        ($request | to json))

    if $response.success {
        _print $"✅ Test environment created: ($response.environment_id)"
        $response
    } else {
        _print $"🛑 Failed to create environment: ($response.message)"
        $response
    }
}

# Create single taskserv test environment
export def "test env single" [
    taskserv: string         # Taskserv name
    --base-image: string = "ubuntu:22.04"
    --cpu: int = 1000        # CPU millicores
    --memory: int = 2048     # Memory MB
    --infra (-i): string
    --auto-start
    --auto-cleanup
] {
    let config = {
        type: "single_taskserv",
        taskserv: $taskserv,
        base_image: $base_image,
        environment: {},
        resources: {
            cpu_millicores: $cpu,
            memory_mb: $memory,
            disk_gb: null
        }
    }

    test env create $config --infra $infra --auto-start=$auto_start --auto-cleanup=$auto_cleanup
}

# Create server simulation test environment
export def "test env server" [
    server_name: string      # Server name
    taskservs: list<string>  # List of taskservs
    --base-image: string = "ubuntu:22.04"
    --cpu: int = 2000
    --memory: int = 4096
    --infra (-i): string
    --auto-start
    --auto-cleanup
] {
    let config = {
        type: "server_simulation",
        server_name: $server_name,
        taskservs: $taskservs,
        base_image: $base_image,
        auto_resolve_dependencies: true,
        environment: {},
        resources: {
            cpu_millicores: $cpu,
            memory_mb: $memory,
            disk_gb: null
        }
    }

    test env create $config --infra $infra --auto-start=$auto_start --auto-cleanup=$auto_cleanup
}

# Create cluster topology test environment
export def "test env cluster" [
    cluster_type: string     # Cluster type (kubernetes, etcd)
    topology: record         # Topology configuration
    --infra (-i): string
    --auto-start
    --auto-cleanup
] {
    let config = {
        type: "cluster_topology",
        ...$topology
    }

    test env create $config --infra $infra --auto-start=$auto_start --auto-cleanup=$auto_cleanup
}

# List test environments
export def "test env list" [
    --orchestrator: string = $DEFAULT_ORCHESTRATOR
] {
    # Use plugin for local orchestrator (<10ms vs ~50ms with HTTP)
    if (use-local-plugin $orchestrator) {
        let all_tasks = (orch tasks)
        # Filter for test environment tasks
        let test_tasks = ($all_tasks | where workflow_id =~ "test-env")
        return ($test_tasks | select id status priority created_at)
    }

    # Fall back to HTTP for remote orchestrators
    let response = (http get $"($orchestrator)/test/environments")

    if $response.success {
        $response.data | select id env_type status created_at containers
    } else {
        []
    }
}

# Get test environment details
export def "test env get" [
    env_id: string
    --orchestrator: string = $DEFAULT_ORCHESTRATOR
] {
    # Use plugin for local orchestrator (~5ms vs ~50ms with HTTP)
    if (use-local-plugin $orchestrator) {
        let all_tasks = (orch tasks)
        let task = ($all_tasks | where id == $env_id | first)

        if ($task | is-empty) {
            error make {msg: $"Environment ($env_id) not found"}
        }

        return $task
    }

    # Fall back to HTTP for remote orchestrators
    let response = (http get $"($orchestrator)/test/environments/($env_id)")

    if $response.success {
        $response.data
    } else {
        error make {msg: $"Environment ($env_id) not found"}
    }
}

# Run tests in environment
export def "test env run" [
    env_id: string
    --tests: list<string> = []
    --timeout: int
    --orchestrator: string = $DEFAULT_ORCHESTRATOR
] {
    let request = {
        tests: $tests,
        timeout_seconds: $timeout
    }

    let response = (http post $"($orchestrator)/test/environments/($env_id)/run"
        --content-type "application/json"
        ($request | to json))

    if $response.success {
        _print $"\n(_ansi cyan_bold)Test Results(_ansi reset)"

        let results = $response.data
        let passed = ($results | where passed == true | length)
        let total = ($results | length)

        for result in $results {
            let icon = if $result.passed {
                $"(_ansi green)✓(_ansi reset)"
            } else {
                $"(_ansi red)✗(_ansi reset)"
            }
            _print $"($icon) ($result.name): ($result.duration_ms)ms"
            if not $result.passed and ($result.error | is-not-empty) {
                _print $"    Error: ($result.error)"
            }
        }

        _print $"\n($passed)/($total) tests passed"
        $results
    } else {
        error make {msg: "Failed to run tests"}
    }
}

# Get environment logs
export def "test env logs" [
    env_id: string
    --orchestrator: string = $DEFAULT_ORCHESTRATOR
] {
    # Logs endpoint requires HTTP (no plugin support for logs yet)
    let response = (http get $"($orchestrator)/test/environments/($env_id)/logs")

    if $response.success {
        $response.data
    } else {
        []
    }
}

# Cleanup test environment
export def "test env cleanup" [
    env_id: string
    --orchestrator: string = $DEFAULT_ORCHESTRATOR
] {
    let response = (http delete $"($orchestrator)/test/environments/($env_id)")

    if $response.success {
        _print $"✅ Environment ($env_id) cleaned up"
    } else {
        _print $"🛑 Failed to cleanup environment"
    }
}

# Show environment status
export def "test env status" [
    env_id: string
    --orchestrator: string = $DEFAULT_ORCHESTRATOR
] {
    let env = (test env get $env_id --orchestrator $orchestrator)

    _print $"\n(_ansi cyan_bold)Test Environment Status(_ansi reset)"
    _print $"ID: ($env.id)"
    _print $"Type: ($env.env_type)"
    _print $"Status: ($env.status)"
    _print $"Created: ($env.created_at)"

    _print $"\n(_ansi cyan)Containers:(_ansi reset)"
    for container in $env.containers {
        _print $"  • ($container.container_name) - ($container.status)"
        if ($container.ip_address | is-not-empty) {
            _print $"    IP: ($container.ip_address)"
        }
    }

    if ($env.test_results | length) > 0 {
        _print $"\n(_ansi cyan)Test Results:(_ansi reset)"
        let passed = ($env.test_results | where passed == true | length)
        let total = ($env.test_results | length)
        _print $"  ($passed)/($total) tests passed"
    }
}

# Load topology template
export def "test topology load" [
    template_name: string
] {
    let config_path = $"($env.PROVISIONING_PATH?)/config/test-topologies.toml"

    if not ($config_path | path exists) {
        error make {msg: $"Topology templates not found: ($config_path)"}
    }

    let topologies = (open $config_path)

    if $template_name in ($topologies | columns) {
        $topologies | get $template_name
    } else {
        error make {msg: $"Topology template ($template_name) not found"}
    }
}

# List available topology templates
export def "test topology list" [] {
    let config_path = $"($env.PROVISIONING_PATH?)/config/test-topologies.toml"

    if not ($config_path | path exists) {
        return []
    }

    let topologies = (open $config_path)

    $topologies | transpose name config | select name
}

# Quick test - create, run, and cleanup
export def "test quick" [
    taskserv: string
    --infra (-i): string
] {
    _print $"🧪 Quick test for ($taskserv)"

    let env_response = (test env single $taskserv --infra $infra --auto-start)

    if not $env_response.success {
        _print $"🛑 Failed to create environment"
        return
    }

    let env_id = $env_response.environment_id

    _print $"⏳ Waiting for environment to be ready..."
    sleep 5sec

    let status = (test env get $env_id)

    if $status.status == "ready" or $status.status == "running" {
        _print $"✅ Environment ready, running tests..."
        test env run $env_id
    }

    _print $"🧹 Cleaning up..."
    test env cleanup $env_id

    _print $"✅ Quick test completed"
}
