#!/usr/bin/env nu

# Taskserv Creation Helper Tool
# Modern Nushell-compatible tool for creating taskservs with guided setup

use ../core/nulib/taskservs/discover.nu *

# Main command dispatcher
def main [
    command?: string    # Command: create, interactive, template, discover, help
    name?: string       # Taskserv name (for create command)
    --category: string  # Taskserv category
    --port: int = 8080  # Default port
    --description: string = ""  # Service description
    --author: string = "Developer"  # Author name
    --template: string = "basic"  # Template type
    --output: string = "provisioning/extensions"  # Output directory
] {
    match $command {
        "create" => {
            if ($name | is-empty) {
                error make { msg: "Taskserv name is required for create command" }
            }
            create_taskserv $name $category $port $description $author $output
        }
        "interactive" | null => {
            interactive_create
        }
        "template" => {
            if ($name | is-empty) {
                create_workspace_template
            } else {
                create_workspace_template $name
            }
        }
        "discover" => {
            show_discovery_info
        }
        "help" => {
            show_help
        }
        _ => {
            print $"Unknown command: ($command)"
            show_help
        }
    }
}

# Interactive taskserv creation
def interactive_create [] {
    print "🚀 Interactive Taskserv Creator"
    print ""

    # Get basic information
    let name = input "📝 Enter taskserv name (kebab-case, e.g., 'my-api'):"

    if ($name | is-empty) or ($name | str contains " ") {
        error make { msg: "Taskserv name must be kebab-case without spaces" }
    }

    # Select category
    let categories = [
        "container-runtime"
        "databases"
        "development"
        "infrastructure"
        "kubernetes"
        "networking"
        "storage"
    ]

    print ""
    print "📂 Available categories:"
    for i in 0..($categories | length) {
        let cat = ($categories | get $i)
        print $"   ($i + 1). ($cat)"
    }

    let category_choice = input "Select category (1-7):"
    let category_index = (($category_choice | into int) - 1)

    if $category_index < 0 or $category_index >= ($categories | length) {
        error make { msg: "Invalid category selection" }
    }

    let category = ($categories | get $category_index)

    # Get additional info
    let description = input $"📄 Enter description for ($name) (optional):"
    let author = input "👤 Enter author name (optional):" --default "Developer"

    # Service type specific questions
    let port = match $category {
        "databases" => {
            let db_ports = {
                "postgres": 5432,
                "redis": 6379,
                "mysql": 3306,
                "mongodb": 27017
            }
            if ($name | str contains "postgres") { 5432 }
            else if ($name | str contains "redis") { 6379 }
            else if ($name | str contains "mysql") { 3306 }
            else if ($name | str contains "mongo") { 27017 }
            else { 5432 }
        }
        "development" => {
            if ($name | str contains "api") or ($name | str contains "web") { 8080 }
            else { 3000 }
        }
        _ => 8080
    }

    let port_input = input $"🔌 Enter port number (default: ($port)):"
    let final_port = if ($port_input | is-empty) { $port } else { $port_input | into int }

    print ""
    print "📋 Creating taskserv with:"
    print $"   Name: ($name)"
    print $"   Category: ($category)"
    print $"   Port: ($final_port)"
    print $"   Description: ($description)"
    print $"   Author: ($author)"
    print ""

    let confirm = input "✅ Proceed with creation? (y/N):"
    if not ($confirm | str downcase | str starts-with "y") {
        print "❌ Creation cancelled"
        return
    }

    create_taskserv $name $category $final_port $description $author "provisioning/extensions"
}

# Create taskserv with parameters
def create_taskserv [
    name: string
    category: string
    port: int
    description: string
    author: string
    output_dir: string
] {
    print $"🛠️ Creating taskserv: ($name)"

    # Validate name format
    if ($name | str contains " ") or ($name | str contains "_") or ($name != ($name | str downcase)) {
        error make { msg: "Name must be kebab-case (lowercase with hyphens)" }
    }

    # Create directory structure
    let taskserv_path = ($output_dir | path join "taskservs" $category $name)
    let kcl_path = ($taskserv_path | path join "kcl")
    let default_path = ($taskserv_path | path join "default")

    print $"📁 Creating directories..."
    mkdir $kcl_path
    mkdir $default_path

    # Generate variables for templates
    let variables = generate_variables $name $category $port $description $author

    # Create files
    create_kcl_mod $kcl_path $variables
    create_main_schema $kcl_path $variables
    create_version_file $kcl_path $variables
    create_defaults_toml $default_path $variables
    create_install_script $default_path $variables
    create_readme $taskserv_path $variables

    print $"✅ Taskserv created successfully at: ($taskserv_path)"
    print ""
    print "🔄 Next steps:"
    print "1. Customize the configuration in the .k files"
    print "2. Update the installation script"
    print "3. Test discovery:"
    print $"   nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; get-taskserv-info ($name)\""
    print "4. Create a workspace template (optional):"
    print $"   nu provisioning/tools/create-taskserv-helper.nu template ($name)"

    # Show layer resolution test
    print ""
    print "🧪 Test layer resolution:"
    print $"   nu -c \"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($name) wuji upcloud\""
}

# Generate template variables
def generate_variables [
    name: string
    category: string
    port: int
    description: string
    author: string
]: nothing -> record {
    let name_pascal = ($name | split row "-" | each { |word| $word | str capitalize } | str join "")
    let name_snake = ($name | str replace -a "-" "_")
    let display_name = ($name | split row "-" | each { |word| $word | str capitalize } | str join " ")

    let final_description = if ($description | is-empty) {
        $"Deployment and management for ($display_name)"
    } else {
        $description
    }

    {
        name: $name,
        name_pascal: $name_pascal,
        name_snake: $name_snake,
        display_name: $display_name,
        category: $category,
        port: $port,
        description: $final_description,
        author: $author,
        date: (date now | format date "%Y-%m-%d"),
        version: "1.0.0"
    }
}

# Create kcl.mod file
def create_kcl_mod [kcl_path: string, vars: record] {
    let content = $"[package]
name = \"($vars.name)\"
version = \"($vars.version)\"
description = \"($vars.description)\"
authors = [\"($vars.author)\"]

[dependencies]
k8s = { oci = \"oci://ghcr.io/kcl-lang/k8s\", tag = \"1.30\" }
"

    $content | save ($kcl_path | path join "kcl.mod")
    print $"   ✓ Created kcl.mod"
}

# Create main KCL schema
def create_main_schema [kcl_path: string, vars: record] {
    let content = $"# ($vars.display_name) Taskserv Configuration
# ($vars.description)

schema ($vars.name_pascal) {
    # Service metadata
    name: str = \"($vars.name)\"
    version: str = \"latest\"
    namespace: str = \"default\"

    # Service configuration
    replicas: int = 1
    port: int = ($vars.port)

    # Resource requirements
    resources: {
        cpu: str = \"100m\"
        memory: str = \"128Mi\"
        limits?: {
            cpu?: str = \"500m\"
            memory?: str = \"512Mi\"
        }
    } = {
        cpu = \"100m\"
        memory = \"128Mi\"
    }

    # Service specific configuration
    config?: {str: any} = {}

    # Health checks
    health?: {
        enabled: bool = true
        path: str = \"/health\"
        initial_delay: int = 30
        period: int = 10
    } = {
        enabled = true
        path = \"/health\"
        initial_delay = 30
        period = 10
    }
}

# Default configuration
($vars.name_snake)_config: ($vars.name_pascal) = ($vars.name_pascal) {
    name = \"($vars.name)\"
    version = \"latest\"
    replicas = 1
    port = ($vars.port)
}
"

    $content | save ($kcl_path | path join $"($vars.name).k")
    print $"   ✓ Created ($vars.name).k"
}

# Create version file
def create_version_file [kcl_path: string, vars: record] {
    let content = $"# Version information for ($vars.name) taskserv

schema ($vars.name_pascal)Version {
    current: str = \"($vars.version)\"
    compatible: [str] = [\"($vars.version)\"]
    deprecated?: [str] = []
    changelog?: {str: str} = {}
}

($vars.name_snake)_version: ($vars.name_pascal)Version = ($vars.name_pascal)Version {
    current = \"($vars.version)\"
    changelog = {
        \"($vars.version)\" = \"Initial release\"
    }
}
"

    $content | save ($kcl_path | path join "version.k")
    print $"   ✓ Created version.k"
}

# Create defaults TOML
def create_defaults_toml [default_path: string, vars: record] {
    let content = $"# Default configuration for ($vars.name)
# Generated on ($vars.date)

[service]
name = \"($vars.name)\"
version = \"latest\"
port = ($vars.port)
replicas = 1

[deployment]
strategy = \"RollingUpdate\"
max_unavailable = 1
max_surge = 1

[resources]
cpu_request = \"100m\"
cpu_limit = \"500m\"
memory_request = \"128Mi\"
memory_limit = \"512Mi\"

[health]
enabled = true
path = \"/health\"
initial_delay_seconds = 30
period_seconds = 10
timeout_seconds = 5

[networking]
service_type = \"ClusterIP\"
expose_metrics = false
metrics_port = 9090
"

    $content | save ($default_path | path join "defs.toml")
    print $"   ✓ Created defs.toml"
}

# Create installation script
def create_install_script [default_path: string, vars: record] {
    let content = $"#!/bin/bash
set -euo pipefail

# ($vars.display_name) Installation Script
# Generated on ($vars.date)

echo \"🚀 Installing ($vars.name)...\"

# Configuration
SERVICE_NAME=\"${SERVICE_NAME:-($vars.name)}\"
SERVICE_VERSION=\"${SERVICE_VERSION:-latest}\"
NAMESPACE=\"${NAMESPACE:-default}\"
REPLICAS=\"${REPLICAS:-1}\"
PORT=\"${PORT:-($vars.port)}\"

# Validation
if [[ -z \"$SERVICE_NAME\" ]]; then
    echo \"❌ SERVICE_NAME is required\"
    exit 1
fi

echo \"📋 Configuration:\"
echo \"   Service: $SERVICE_NAME\"
echo \"   Version: $SERVICE_VERSION\"
echo \"   Namespace: $NAMESPACE\"
echo \"   Port: $PORT\"
echo \"   Replicas: $REPLICAS\"

# Create namespace if it doesn't exist
echo \"🏗️ Creating namespace...\"
kubectl create namespace \"$NAMESPACE\" --dry-run=client -o yaml | kubectl apply -f -

# Apply deployment
echo \"🚢 Applying deployment...\"
cat <<EOF | envsubst | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: $SERVICE_NAME
  namespace: $NAMESPACE
  labels:
    app: $SERVICE_NAME
spec:
  replicas: $REPLICAS
  selector:
    matchLabels:
      app: $SERVICE_NAME
  template:
    metadata:
      labels:
        app: $SERVICE_NAME
    spec:
      containers:
      - name: $SERVICE_NAME
        image: $SERVICE_NAME:$SERVICE_VERSION
        ports:
        - containerPort: $PORT
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /health
            port: $PORT
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: $PORT
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: $SERVICE_NAME
  namespace: $NAMESPACE
  labels:
    app: $SERVICE_NAME
spec:
  selector:
    app: $SERVICE_NAME
  ports:
  - port: $PORT
    targetPort: $PORT
  type: ClusterIP
EOF

# Wait for deployment
echo \"⏳ Waiting for deployment to be ready...\"
kubectl wait --for=condition=available --timeout=300s deployment/$SERVICE_NAME -n $NAMESPACE

echo \"✅ ($vars.display_name) installed successfully\"
echo \"🔍 Check status with: kubectl get pods -n $NAMESPACE -l app=$SERVICE_NAME\"
"

    $content | save ($default_path | path join $"install-($vars.name).sh")

    # Make script executable
    chmod +x ($default_path | path join $"install-($vars.name).sh")
    print $"   ✓ Created install-($vars.name).sh"
}

# Create README
def create_readme [taskserv_path: string, vars: record] {
    let content = $"# ($vars.display_name) Taskserv

($vars.description)

## Overview

This taskserv provides deployment and management capabilities for ($vars.display_name) in Kubernetes environments.

## Configuration

### Basic Configuration

```kcl
import taskservs.($vars.category).($vars.name).kcl.($vars.name) as ($vars.name_snake)

($vars.name_snake)_config: ($vars.name_snake).($vars.name_pascal) = ($vars.name_snake).($vars.name_snake)_config {
    # Customize configuration
    version = \"1.2.3\"
    replicas = 2
    port = ($vars.port)

    resources = {
        cpu = \"200m\"
        memory = \"256Mi\"
        limits = {
            cpu = \"1000m\"
            memory = \"1Gi\"
        }
    }
}
```

### Advanced Configuration

```kcl
($vars.name_snake)_production: ($vars.name_snake).($vars.name_pascal) = ($vars.name_snake).($vars.name_snake)_config {
    # Production settings
    replicas = 3

    resources = {
        cpu = \"500m\"
        memory = \"512Mi\"
        limits = {
            cpu = \"2000m\"
            memory = \"2Gi\"
        }
    }

    health = {
        enabled = true
        path = \"/healthz\"
        initial_delay = 60
        period = 15
    }

    config = {
        \"log_level\" = \"info\"
        \"metrics_enabled\" = \"true\"
    }
}
```

## Usage

### Deploy with Provisioning System

```bash
# Deploy to infrastructure
provisioning/core/cli/provisioning taskserv create ($vars.name) --infra my-infra --check

# Generate configuration
provisioning/core/cli/provisioning taskserv generate ($vars.name) --infra my-infra
```

### Direct Installation

```bash
# Set environment variables
export SERVICE_VERSION=\"1.2.3\"
export NAMESPACE=\"production\"
export REPLICAS=\"3\"

# Run installation script
cd provisioning/extensions/taskservs/($vars.category)/($vars.name)/default
./install-($vars.name).sh
```

## Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `name` | str | `($vars.name)` | Service name |
| `version` | str | `latest` | Container image version |
| `namespace` | str | `default` | Kubernetes namespace |
| `replicas` | int | `1` | Number of replicas |
| `port` | int | `($vars.port)` | Service port |
| `resources.cpu` | str | `100m` | CPU request |
| `resources.memory` | str | `128Mi` | Memory request |
| `health.enabled` | bool | `true` | Enable health checks |
| `health.path` | str | `/health` | Health check endpoint |
| `config` | object | `{}` | Additional configuration |

## Dependencies

- Kubernetes cluster
- kubectl configured
- Container image: `($vars.name):latest`

## Troubleshooting

### Check Pod Status
```bash
kubectl get pods -n <namespace> -l app=($vars.name)
kubectl describe pod <pod-name> -n <namespace>
```

### View Logs
```bash
kubectl logs -f deployment/($vars.name) -n <namespace>
```

### Debug Configuration
```bash
# Test KCL configuration
kcl run provisioning/extensions/taskservs/($vars.category)/($vars.name)/kcl/($vars.name).k

# Validate deployment
provisioning/core/cli/provisioning taskserv create ($vars.name) --infra <infra> --check
```

### Common Issues

1. **Pod not starting**: Check resource requests and image availability
2. **Health check failures**: Verify health check endpoint and timing
3. **Service not accessible**: Check service configuration and network policies

## Development

### Layer Resolution
This taskserv supports the 3-layer architecture:

1. **Core Layer**: Base configuration in this directory
2. **Workspace Layer**: Templates in `provisioning/workspace/templates/taskservs/($vars.category)/($vars.name).k`
3. **Infrastructure Layer**: Overrides in `workspace/infra/<infra>/task-servs/($vars.name).k`

### Testing
```bash
# Test layer resolution
nu -c \"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($vars.name) <infra> <provider>\"

# Discover taskserv
nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; get-taskserv-info ($vars.name)\"
```

## Contributing

1. Follow the taskserv development guidelines
2. Update version information when making changes
3. Test across different environments
4. Update this README with any new configuration options

## License

MIT License

## Author

($vars.author)

## Generated

Created on ($vars.date) using the Taskserv Helper Tool.
"

    $content | save ($taskserv_path | path join "README.md")
    print $"   ✓ Created README.md"
}

# Create workspace template
def create_workspace_template [name?: string] {
    if ($name == null) or ($name | is-empty) {
        print "📋 Create workspace template for existing taskserv"
        let taskservs = (discover-taskservs | select name category)

        print "Available taskservs:"
        for i in 0..($taskservs | length | $in - 1) {
            let ts = ($taskservs | get $i)
            print $"   ($i + 1). ($ts.name) (($ts.category))"
        }

        let choice = input "Select taskserv number:"
        let index = (($choice | into int) - 1)

        if $index < 0 or $index >= ($taskservs | length) {
            error make { msg: "Invalid selection" }
        }

        let selected = ($taskservs | get $index)
        create_template_for_taskserv $selected.name $selected.category
    } else {
        let taskserv_info = get-taskserv-info $name
        create_template_for_taskserv $taskserv_info.name $taskserv_info.group
    }
}

# Create template for specific taskserv
def create_template_for_taskserv [name: string, category: string] {
    print $"📝 Creating workspace template for ($name)"

    let template_dir = ("provisioning/workspace/templates/taskservs" | path join $category)
    let template_file = ($template_dir | path join $"($name).k")

    mkdir $template_dir

    let name_snake = ($name | str replace -a "-" "_")
    let name_pascal = ($name | str replace -a "-" " " | str title-case | str replace -a " " "")

    let content = $"# Workspace template for ($name) taskserv
import taskservs.($category).($name).kcl.($name) as base

# Template configuration extending base
($name_snake)_template: base.($name_pascal) = base.($name_snake)_config {
    # Template customizations for workspace layer
    # These can be overridden at the infrastructure layer

    # Common template settings
    version = \"stable\"

    # Adjust for template environment
    replicas = 2  # Default for multi-replica setup

    # Template resource defaults
    resources = base.($name_snake)_config.resources {
        cpu = \"200m\"
        memory = \"256Mi\"
        limits = {
            cpu = \"1000m\"
            memory = \"1Gi\"
        }
    }

    # Template-level configuration
    config = {
        \"environment\" = \"template\"
        \"log_level\" = \"info\"
    }
}
"

    $content | save $template_file
    print $"✅ Created workspace template: ($template_file)"

    print ""
    print "🧪 Test the template:"
    print $"   nu -c \"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($name) <infra> <provider>\""
}

# Show discovery information
def show_discovery_info [] {
    print "🔍 Taskserv Discovery Information"
    print ""

    let taskservs = discover-taskservs
    let total = ($taskservs | length)
    let by_group = ($taskservs | group-by group | transpose group taskservs | each { |row| {group: $row.group, count: ($row.taskservs | length)} })

    print $"📊 Total taskservs discovered: ($total)"
    print ""
    print "📂 By category:"

    for group_info in $by_group {
        print $"   ($group_info.group): ($group_info.count) taskservs"
        let group_taskservs = ($taskservs | where group == $group_info.group | get name)
        for taskserv in $group_taskservs {
            print $"      • ($taskserv)"
        }
    }

    print ""
    print "🛠️ Available commands:"
    print "   nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; discover-taskservs\""
    print "   nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; search-taskservs <query>\""
    print "   nu -c \"use provisioning/workspace/tools/layer-utils.nu *; show_layer_stats\""
}

# Show help information
def show_help [] {
    print "🚀 Taskserv Helper Tool"
    print ""
    print "USAGE:"
    print "    nu provisioning/tools/create-taskserv-helper.nu <command> [options]"
    print ""
    print "COMMANDS:"
    print "    interactive          Launch interactive taskserv creator"
    print "    create <name>        Create taskserv with specified name"
    print "    template [name]      Create workspace template for taskserv"
    print "    discover             Show discovery information"
    print "    help                 Show this help message"
    print ""
    print "CREATE OPTIONS:"
    print "    --category <cat>     Taskserv category (required for create)"
    print "    --port <port>        Service port (default: 8080)"
    print "    --description <desc> Service description"
    print "    --author <author>    Author name (default: Developer)"
    print "    --output <dir>       Output directory (default: provisioning/extensions)"
    print ""
    print "CATEGORIES:"
    print "    container-runtime    Container runtime engines"
    print "    databases           Database services"
    print "    development         Development tools"
    print "    infrastructure      System infrastructure"
    print "    kubernetes          Kubernetes orchestration"
    print "    networking          Network services"
    print "    storage             Storage solutions"
    print ""
    print "EXAMPLES:"
    print "    # Interactive creation"
    print "    nu provisioning/tools/create-taskserv-helper.nu interactive"
    print ""
    print "    # Create API service"
    print "    nu provisioning/tools/create-taskserv-helper.nu create my-api \\"
    print "        --category development \\"
    print "        --port 8080 \\"
    print "        --description \"My REST API service\""
    print ""
    print "    # Create database service"
    print "    nu provisioning/tools/create-taskserv-helper.nu create my-db \\"
    print "        --category databases \\"
    print "        --port 5432 \\"
    print "        --author \"Database Team\""
    print ""
    print "    # Create workspace template"
    print "    nu provisioning/tools/create-taskserv-helper.nu template my-api"
    print ""
    print "📖 For more information, see:"
    print "    docs/development/TASKSERV_DEVELOPER_GUIDE.md"
    print "    docs/development/TASKSERV_QUICK_GUIDE.md"
}

# String utility functions
def "str title-case" [] {
    let text = $in
    $text | split row " " | each { |word|
        if ($word | is-empty) {
            $word
        } else {
            ($word | str substring 0..1 | str upcase) + ($word | str substring 1..)
        }
    } | str join " "
}
