package cli

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/WAH-ISHAN/backlist-npm/devops/internal/config"
	"github.com/WAH-ISHAN/backlist-npm/devops/internal/logger"
	"github.com/WAH-ISHAN/backlist-npm/devops/internal/plugins"
)

// Config holds CLI configuration
type Config struct {
	Name    string
	Version string
	Logger  *logger.Logger
}

// CLI represents the main CLI application
type CLI struct {
	name    string
	version string
	logger  *logger.Logger
	config  *config.Config
	plugins map[string]plugins.Plugin
}

// New creates a new CLI instance
func New(cfg Config) *CLI {
	return &CLI{
		name:    cfg.Name,
		version: cfg.Version,
		logger:  cfg.Logger,
		plugins: make(map[string]plugins.Plugin),
	}
}

// Run executes the CLI application
func (c *CLI) Run(args []string) error {
	if len(args) < 2 {
		return c.Help()
	}

	// Register default plugins
	c.registerPlugins()

	// Parse command
	cmd := args[1]

	switch cmd {
	case "help", "--help", "-h":
		return c.Help()

	case "version", "--version", "-v":
		return c.Version()

	case "init":
		return c.Init(args[2:])

	case "doctor":
		return c.Doctor()

	case "build":
		return c.Build(args[2:])

	case "run":
		return c.RunContainer(args[2:])

	case "up":
		return c.Up(args[2:])

	case "down":
		return c.Down(args[2:])

	case "deploy":
		return c.Deploy(args[2:])

	case "rollback":
		return c.Rollback(args[2:])

	case "status":
		return c.Status(args[2:])

	case "scale":
		return c.Scale(args[2:])

	case "logs":
		return c.Logs(args[2:])

	case "exec":
		return c.Exec(args[2:])

	case "shell":
		return c.Shell(args[2:])

	case "top":
		return c.Top(args[2:])

	case "clean":
		return c.Clean(args[2:])

	case "config":
		return c.Config(args[2:])

	case "infra":
		return c.Infra(args[2:])

	case "ci":
		return c.CI(args[2:])

	case "plugin":
		return c.Plugin(args[2:])

	default:
		fmt.Printf("Unknown command: %s\n", cmd)
		return c.Help()
	}
}

// Help displays help information
func (c *CLI) Help() error {
	fmt.Printf(`
🛠️  DevOps CLI - All-in-One DevOps Command Center

Version: %s

Usage:
  devops <command> [flags]

Commands:
  ╔══════════════════════════════════════════════════════════════════╗
  ║ Project Management                                                ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║  init         Initialize a new DevOps project                      ║
  ║  doctor       Check environment and dependencies                   ║
  ║  config       View and edit configuration                          ║
  ║                                                                ║
  ║ Build & Run                                                     ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║  build        Build Docker images                                 ║
  ║  run          Run containers locally                              ║
  ║  up           Start full development environment                  ║
  ║  down         Stop all services                                   ║
  ║                                                                ║
  ║ Deployment                                                       ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║  deploy       Deploy to Kubernetes                                ║
  ║  rollback     Rollback to previous version                        ║
  ║  scale        Scale deployments                                   ║
  ║  status       View deployment status                              ║
  ║                                                                ║
  ║ Infrastructure                                                   ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║  infra        Infrastructure management (plan|apply|destroy)      ║
  ║                                                                ║
  ║ CI/CD                                                           ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║  ci           CI/CD operations (run|deploy|status)                ║
  ║                                                                ║
  ║ Monitoring                                                       ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║  logs         Stream logs                                         ║
  ║  exec         Execute command in container                         ║
  ║  shell        Shell into container                                ║
  ║  top          View resource usage                                 ║
  ║  clean        Clean up resources                                  ║
  ║                                                                ║
  ║ Utilities                                                        ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║  plugin       Plugin management                                   ║
  ║  version      Show version information                            ║
  ║  help         Show this help message                              ║
  ╚══════════════════════════════════════════════════════════════════╝

Flags:
  -h, --help     Show help for a command
  -v, --version  Show version information
  --verbose      Enable verbose output
  --dry-run      Show what would be executed

Examples:
  devops init
  devops doctor
  devops build --tag v1.0.0
  devops up
  devops deploy --env production

For more information, see: https://github.com/WAH-ISHAN/backlist-npm/devops

`, c.version)
	return nil
}

// Version displays version information
func (c *CLI) Version() error {
	fmt.Printf(`
🚀 DevOps CLI
Version: %s
Build: %s
Go: %s

A comprehensive, modular DevOps CLI that orchestrates:
• Docker & Docker Compose
• Kubernetes & Helm
• Terraform & Pulumi
• CI/CD Pipelines
• Cloud Providers (AWS, Azure, GCP)

Built with ❤️ by W.A.H. ISHAN

`, c.version, "0000000", runtime.Version())
	return nil
}

// registerPlugins registers all built-in plugins
func (c *CLI) registerPlugins() {
	// Docker plugin
	c.plugins["docker"] = plugins.NewDockerPlugin()

	// Kubernetes plugin
	c.plugins["kubernetes"] = plugins.NewKubernetesPlugin()

	// Helm plugin
	c.plugins["helm"] = plugins.NewHelmPlugin()

	// Terraform plugin
	c.plugins["terraform"] = plugins.NewTerraformPlugin()

	// CI plugins
	c.plugins["github"] = plugins.NewGitHubPlugin()
	c.plugins["gitlab"] = plugins.NewGitLabPlugin()
	c.plugins["jenkins"] = plugins.NewJenkinsPlugin()

	// Cloud plugins
	c.plugins["aws"] = plugins.NewAWSPlugin()
	c.plugins["azure"] = plugins.NewAzurePlugin()
	c.plugins["gcp"] = plugins.NewGCPPlugin()
}

// Init initializes a new DevOps project
func (c *CLI) Init(args []string) error {
	fmt.Println("🚀 Initializing DevOps project...")

	// Check if devops.yml already exists
	if _, err := os.Stat("devops.yml"); err == nil {
		fmt.Println("⚠️  devops.yml already exists")
		return nil
	}

	// Create default configuration
	cfg := config.Default()
	if err := cfg.Save("devops.yml"); err != nil {
		return fmt.Errorf("failed to save config: %w", err)
	}

	fmt.Println("✅ Created devops.yml")
	fmt.Println("📁 Project structure:")

	// Create directory structure
	dirs := []string{
		"charts",
		"kubernetes",
		"terraform",
		"scripts",
		".github/workflows",
	}

	for _, dir := range dirs {
		if err := os.MkdirAll(dir, 0755); err != nil {
			fmt.Printf("⚠️  Failed to create %s: %v\n", dir, err)
		} else {
			fmt.Printf("   ├── %s/\n", dir)
		}
	}

	// Create Dockerfile if not exists
	if _, err := os.Stat("Dockerfile"); os.IsNotExist(err) {
		dockerfile := `FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o main .

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
COPY --from=builder /app/configs ./configs
EXPOSE 8080
CMD ["./main"]
`
		if err := os.WriteFile("Dockerfile", []byte(dockerfile), 0644); err == nil {
			fmt.Println("   ├── Dockerfile")
		}
	}

	// Create docker-compose.yml if not exists
	if _, err := os.Stat("docker-compose.yml"); os.IsNotExist(err) {
		compose := `version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - NODE_ENV=development
    depends_on:
      - db
      - redis
    volumes:
      - .:/app
      - /app/node_modules

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:
`
		if err := os.WriteFile("docker-compose.yml", []byte(compose), 0644); err == nil {
			fmt.Println("   ├── docker-compose.yml")
		}
	}

	// Create Kubernetes manifests
	if err := os.MkdirAll("kubernetes/base", 0755); err == nil {
		deployment := `apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: app
          image: myapp:latest
          ports:
            - containerPort: 8080
          resources:
            requests:
              memory: "64Mi"
              cpu: "250m"
            limits:
              memory: "128Mi"
              cpu: "500m"
`
		if err := os.WriteFile("kubernetes/base/deployment.yaml", []byte(deployment), 0644); err == nil {
			fmt.Println("   ├── kubernetes/base/deployment.yaml")
		}

		service := `apiVersion: v1
kind: Service
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: myapp
`
		if err := os.WriteFile("kubernetes/base/service.yaml", []byte(service), 0644); err == nil {
			fmt.Println("   ├── kubernetes/base/service.yaml")
		}
	}

	fmt.Println("\n✅ Project initialized successfully!")
	fmt.Println("\nNext steps:")
	fmt.Println("  1. Customize devops.yml for your project")
	fmt.Println("  2. Update Dockerfile for your application")
	fmt.Println("  3. Run 'devops doctor' to check dependencies")
	fmt.Println("  4. Run 'devops up' to start development environment")

	return nil
}

// Doctor checks environment and dependencies
func (c *CLI) Doctor() error {
	fmt.Println("🔍 Checking development environment...\n")

	checks := []struct {
		name    string
		check   func() bool
		suggest string
	}{
		{"Docker", checkDocker, "Install Docker: https://docs.docker.com/get-docker/"},
		{"Docker Compose", checkDockerCompose, "Install Docker Compose: https://docs.docker.com/compose/install/"},
		{"Kubernetes (kubectl)", checkKubectl, "Install kubectl: https://kubernetes.io/docs/tasks/tools/"},
		{"Helm", checkHelm, "Install Helm: https://helm.sh/docs/intro/install/"},
		{"Terraform", checkTerraform, "Install Terraform: https://www.terraform.io/downloads"},
		{"Git", checkGit, "Install Git: https://git-scm.com/downloads"},
		{"Go", checkGo, "Install Go: https://go.dev/dl/"},
		{"Node.js", checkNode, "Install Node.js: https://nodejs.org/"},
		{"Python", checkPython, "Install Python: https://www.python.org/downloads/"},
	}

	allPassed := true
	for _, tc := range checks {
		status := "✅"
		color := "\033[92m"
		if !tc.check() {
			status = "❌"
			color = "\033[91m"
			allPassed = false
		}
		fmt.Printf("%s[%s]\033[0m %s\n", color, status, tc.name)
		if !tc.check() {
			fmt.Printf("   → %s\n", tc.suggest)
		}
	}

	fmt.Println()
	if allPassed {
		fmt.Println("✅ All dependencies are installed!")
	} else {
		fmt.Println("⚠️  Some dependencies are missing. Install them to use all features.")
	}

	// Check cloud credentials
	fmt.Println("\n☁️  Cloud Provider Credentials:")
	cloudChecks := []struct {
		name  string
		check func() bool
	}{
		{"AWS", checkAWSCredentials},
		{"Azure", checkAzureCredentials},
		{"GCP", checkGCPCredentials},
	}

	for _, cc := range cloudChecks {
		status := "✅"
		color := "\033[92m"
		if !cc.check() {
			status = "⚠️"
			color = "\033[93m"
		}
		fmt.Printf("%s[%s]\033[0m %s\n", color, status, cc.name)
	}

	// Check Docker daemon
	fmt.Println("\n🐳 Docker Status:")
	if checkDocker() {
		if err := c.runCommand("docker", "info"); err != nil {
			fmt.Println("⚠️  Docker daemon is not running. Start Docker to build and run containers.")
		} else {
			fmt.Println("✅ Docker daemon is running")
		}
	}

	// Check Kubernetes connection
	fmt.Println("\n☸️  Kubernetes Status:")
	if checkKubectl() {
		if err := c.runCommand("kubectl", "cluster-info"); err != nil {
			fmt.Println("⚠️  Not connected to a Kubernetes cluster")
		} else {
			fmt.Println("✅ Connected to Kubernetes cluster")
		}
	}

	return nil
}

// Build builds Docker images
func (c *CLI) Build(args []string) error {
	fmt.Println("🔨 Building Docker images...")

	// Load configuration
	cfg, err := config.Load("devops.yml")
	if err != nil {
		// Use defaults if no config
		cfg = config.Default()
	}

	// Determine image name and tag
	image := "myapp"
	tag := "latest"
	context := "."
	dockerfile := "Dockerfile"

	for i, arg := range args {
		switch arg {
		case "-t", "--tag":
			if i+1 < len(args) {
				tag = args[i+1]
			}
		case "-f", "--file":
			if i+1 < len(args) {
				dockerfile = args[i+1]
			}
		case "--no-cache":
			// Will be handled below
		}
	}

	// Use config values if available
	if cfg.Docker.Image != "" {
		image = cfg.Docker.Image
	}
	if cfg.Docker.Context != "" {
		context = cfg.Docker.Context
	}
	if cfg.Docker.Dockerfile != "" {
		dockerfile = cfg.Docker.Dockerfile
	}

	fullImage := fmt.Sprintf("%s:%s", image, tag)

	fmt.Printf("   Image: %s\n", fullImage)
	fmt.Printf("   Context: %s\n", context)
	fmt.Printf("   Dockerfile: %s\n", dockerfile)

	// Build command
	argsBuild := []string{"build", "-t", fullImage}

	// Add BuildKit support
	argsBuild = append(argsBuild, "--build-arg", "BUILDKIT=1")

	// Add no-cache if specified
	for _, arg := range args {
		if arg == "--no-cache" {
			argsBuild = append(argsBuild, "--no-cache")
			break
		}
	}

	argsBuild = append(argsBuild, "-f", dockerfile, context)

	if err := c.runCommand("docker", argsBuild...); err != nil {
		return fmt.Errorf("failed to build Docker image: %w", err)
	}

	fmt.Printf("\n✅ Successfully built image: %s\n", fullImage)
	fmt.Println("   Run 'devops run' to start the container")
	fmt.Println("   Run 'devops deploy' to deploy to Kubernetes")

	return nil
}

// RunContainer runs a Docker container
func (c *CLI) RunContainer(args []string) error {
	fmt.Println("🐳 Starting container...")

	// Check if docker-compose is requested
	for _, arg := range args {
		if arg == "-f" || arg == "--file" {
			return c.runCompose(args)
		}
	}

	// Run single container
	if err := c.runCommand("docker", append([]string{"run", "-it", "--rm"}, args...)...); err != nil {
		return fmt.Errorf("failed to run container: %w", err)
	}

	return nil
}

// Up starts the full development environment
func (c *CLI) Up(args []string) error {
	fmt.Println("🚀 Starting development environment...\n")

	// Load configuration
	cfg, err := config.Load("devops.yml")
	if err != nil {
		cfg = config.Default()
	}

	// Check if using compose
	if cfg.Compose.File != "" {
		return c.runCompose([]string{"-f", cfg.Compose.File, "up", "-d"})
	}

	// Start services individually
	fmt.Println("📦 Building and starting services...")

	// Build images
	if err := c.Build([]string{}); err != nil {
		fmt.Printf("⚠️  Build warning: %v\n", err)
	}

	// Start database if configured
	if cfg.Database.Type != "" {
		fmt.Printf("   Starting %s database...\n", cfg.Database.Type)
		// Start database based on type
	}

	// Start application
	fmt.Println("   Starting application...")

	// Run with docker-compose if available
	if _, err := os.Stat("docker-compose.yml"); err == nil {
		return c.runCompose([]string{"-f", "docker-compose.yml", "up", "-d"})
	}

	// Fallback to docker run
	image := "myapp:latest"
	if cfg.Docker.Image != "" {
		image = fmt.Sprintf("%s:latest", cfg.Docker.Image)
	}

	fmt.Printf("   Running %s\n", image)
	if err := c.runCommand("docker", "run", "-it", "--rm", "-p", "8080:8080", image); err != nil {
		return fmt.Errorf("failed to start container: %w", err)
	}

	return nil
}

// Down stops all services
func (c *CLI) Down(args []string) error {
	fmt.Println("🛑 Stopping services...")

	// Load configuration
	cfg, err := config.Load("devops.yml")
	if err != nil {
		cfg = config.Default()
	}

	// Stop docker-compose if available
	if cfg.Compose.File != "" {
		return c.runCompose([]string{"-f", cfg.Compose.File, "down"})
	}

	if _, err := os.Stat("docker-compose.yml"); err == nil {
		return c.runCompose([]string{"-f", "docker-compose.yml", "down"})
	}

	// Stop running containers
	fmt.Println("   Stopping containers...")
	if err := c.runCommand("docker", "stop", "$(docker ps -q)"); err != nil {
		fmt.Printf("⚠️  Warning: %v\n", err)
	}

	fmt.Println("✅ All services stopped")
	return nil
}

// Deploy deploys to Kubernetes
func (c *CLI) Deploy(args []string) error {
	fmt.Println("☸️  Deploying to Kubernetes...")

	// Load configuration
	cfg, err := config.Load("devops.yml")
	if err != nil {
		cfg = config.Default()
	}

	namespace := "default"
	env := "development"

	for i, arg := range args {
		switch arg {
		case "-n", "--namespace":
			if i+1 < len(args) {
				namespace = args[i+1]
			}
		case "-e", "--env":
			if i+1 < len(args) {
				env = args[i+1]
			}
		}
	}

	if cfg.Kubernetes.Namespace != "" {
		namespace = cfg.Kubernetes.Namespace
	}

	fmt.Printf("   Namespace: %s\n", namespace)
	fmt.Printf("   Environment: %s\n", env)

	// Build and push image first
	fmt.Println("\n📦 Building and pushing image...")
	if err := c.Build([]string{}); err != nil {
		fmt.Printf("⚠️  Build warning: %v\n", err)
	}

	// Push to registry
	image := cfg.Docker.Image
	if image == "" {
		image = "myapp"
	}
	fmt.Println("   Note: Push image to registry for production deployments")

	// Deploy with kubectl
	fmt.Println("\n🚀 Applying Kubernetes manifests...")

	kubePath := "kubernetes/base"
	if _, err := os.Stat(kubePath); os.IsNotExist(err) {
		kubePath = "kubernetes"
	}

	// Apply Kubernetes manifests
	if err := c.runCommand("kubectl", "apply", "-f", kubePath, "-n", namespace); err != nil {
		fmt.Printf("⚠️  kubectl apply warning: %v\n", err)
		fmt.Println("   You may need to create Kubernetes manifests first")
	}

	// Wait for rollout
	fmt.Println("\n⏳ Waiting for rollout to complete...")
	if err := c.runCommand("kubectl", "rollout", "status", "deployment/myapp", "-n", namespace); err != nil {
		fmt.Printf("⚠️  Rollout status warning: %v\n", err)
	}

	// Show status
	fmt.Println("\n📊 Deployment Status:")
	if err := c.runCommand("kubectl", "get", "pods", "-n", namespace); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	fmt.Println("\n✅ Deployment initiated!")
	fmt.Println("   Run 'devops status' for detailed status")
	fmt.Println("   Run 'devops logs' to view logs")

	return nil
}

// Rollback rolls back to previous version
func (c *CLI) Rollback(args []string) error {
	fmt.Println("↩️  Rolling back deployment...")

	namespace := "default"
	for i, arg := range args {
		if arg == "-n" || arg == "--namespace" {
			if i+1 < len(args) {
				namespace = args[i+1]
			}
		}
	}

	if err := c.runCommand("kubectl", "rollout", "undo", "deployment/myapp", "-n", namespace); err != nil {
		return fmt.Errorf("failed to rollback: %w", err)
	}

	fmt.Println("⏳ Waiting for rollback to complete...")
	if err := c.runCommand("kubectl", "rollout", "status", "deployment/myapp", "-n", namespace); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	fmt.Println("✅ Rollback complete!")
	return nil
}

// Status shows deployment status
func (c *CLI) Status(args []string) error {
	fmt.Println("📊 Deployment Status\n")

	namespace := "default"
	for i, arg := range args {
		if arg == "-n" || arg == "--namespace" {
			if i+1 < len(args) {
				namespace = args[i+1]
			}
		}
	}

	// Check Kubernetes status
	fmt.Println("☸️  Kubernetes Resources:")
	if err := c.runCommand("kubectl", "get", "all", "-n", namespace); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	// Check pod status
	fmt.Println("\n📦 Pods:")
	if err := c.runCommand("kubectl", "get", "pods", "-n", namespace, "-o", "wide"); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	// Check services
	fmt.Println("\n🌐 Services:")
	if err := c.runCommand("kubectl", "get", "services", "-n", namespace); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	// Check helm releases
	fmt.Println("\n📋 Helm Releases:")
	if err := c.runCommand("helm", "list", "-n", namespace); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	return nil
}

// Scale scales deployments
func (c *CLI) Scale(args []string) error {
	fmt.Println("📈 Scaling deployment...")

	namespace := "default"
	replicas := 3

	for i, arg := range args {
		switch arg {
		case "-n", "--namespace":
			if i+1 < len(args) {
				namespace = args[i+1]
			}
		case "-r", "--replicas":
			if i+1 < len(args) {
				fmt.Sscanf(args[i+1], "%d", &replicas)
			}
		}
	}

	deployment := "myapp"
	for i, arg := range args {
		if arg == "-d" || arg == "--deployment" {
			if i+1 < len(args) {
				deployment = args[i+1]
			}
		}
	}

	if err := c.runCommand("kubectl", "scale", "deployment", deployment,
		"--replicas", fmt.Sprintf("%d", replicas), "-n", namespace); err != nil {
		return fmt.Errorf("failed to scale: %w", err)
	}

	fmt.Printf("✅ Scaled %s to %d replicas\n", deployment, replicas)
	return nil
}

// Logs shows logs
func (c *CLI) Logs(args []string) error {
	fmt.Println("📜 Streaming logs...\n")

	namespace := "default"
	follow := true
	pod := ""

	for i, arg := range args {
		switch arg {
		case "-n", "--namespace":
			if i+1 < len(args) {
				namespace = args[i+1]
			}
		case "--no-follow":
			follow = false
		case "-p", "--pod":
			if i+1 < len(args) {
				pod = args[i+1]
			}
		}
	}

	logArgs := []string{"logs"}

	if follow {
		logArgs = append(logArgs, "-f")
	}

	if pod != "" {
		logArgs = append(logArgs, pod)
	} else {
		logArgs = append(logArgs, "-l", "app=myapp")
	}

	logArgs = append(logArgs, "-n", namespace)

	return c.runCommand("kubectl", logArgs...)
}

// Exec executes command in container
func (c *CLI) Exec(args []string) error {
	fmt.Println("🔧 Executing in container...")

	namespace := "default"
	pod := ""
	command := []string{"/bin/sh"}

	for i, arg := range args {
		switch arg {
		case "-n", "--namespace":
			if i+1 < len(args) {
				namespace = args[i+1]
			}
		case "-p", "--pod":
			if i+1 < len(args) {
				pod = args[i+1]
			}
		case "-c", "--command":
			if i+1 < len(args) {
				command = []string{args[i+1]}
			}
		}
	}

	if pod == "" {
		// Get first pod
		pod = "myapp-0"
		fmt.Printf("   Using pod: %s\n", pod)
	}

	execArgs := []string{"exec", "-it", "-n", namespace, pod}
	execArgs = append(execArgs, command...)

	return c.runCommand("kubectl", execArgs...)
}

// Shell opens shell in container
func (c *CLI) Shell(args []string) error {
	return c.Exec(append(args, "-c", "/bin/sh"))
}

// Top shows resource usage
func (c *CLI) Top(args []string) error {
	fmt.Println("📊 Resource Usage\n")

	// Check Docker stats
	fmt.Println("🐳 Docker Containers:")
	if err := c.runCommand("docker", "stats", "--no-stream"); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	// Check Kubernetes pods
	fmt.Println("\n☸️  Kubernetes Pods:")
	if err := c.runCommand("kubectl", "top", "pods"); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	// Check nodes
	fmt.Println("\n🖥️  Kubernetes Nodes:")
	if err := c.runCommand("kubectl", "top", "nodes"); err != nil {
		fmt.Printf("⚠️  %v\n", err)
	}

	return nil
}

// Clean cleans up resources
func (c *CLI) Clean(args []string) error {
	fmt.Println("🧹 Cleaning up resources...")

	// Stop containers
	fmt.Println("   Stopping containers...")
	c.runCommand("docker", "stop", "$(docker ps -q)")

	// Remove stopped containers
	fmt.Println("   Removing stopped containers...")
	c.runCommand("docker", "container", "prune", "-f")

	// Remove unused images
	fmt.Println("   Removing unused images...")
	c.runCommand("docker", "image", "prune", "-f")

	// Remove unused volumes
	fmt.Println("   Removing unused volumes...")
	c.runCommand("docker", "volume", "prune", "-f")

	// Remove build cache
	fmt.Println("   Removing build cache...")
	c.runCommand("docker", "builder", "prune", "-f")

	fmt.Println("\n✅ Cleanup complete!")
	return nil
}

// Config manages configuration
func (c *CLI) Config(args []string) error {
	if len(args) == 0 {
		return c.showConfig()
	}

	subCmd := args[0]
	switch subCmd {
	case "show", "view":
		return c.showConfig()
	case "edit":
		fmt.Println("   Open devops.yml in your editor")
		return c.runCommand("nano", "devops.yml")
	case "validate":
		_, err := config.Load("devops.yml")
		if err != nil {
			return fmt.Errorf("invalid config: %w", err)
		}
		fmt.Println("✅ Configuration is valid")
		return nil
	default:
		return c.showConfig()
	}
}

// showConfig displays current configuration
func (c *CLI) showConfig() error {
	cfg, err := config.Load("devops.yml")
	if err != nil {
		cfg = config.Default()
		fmt.Println("No devops.yml found. Using defaults:\n")
	} else {
		fmt.Println("Current Configuration:\n")
	}

	fmt.Printf("Project: %s\n", cfg.Project.Name)
	fmt.Printf("Docker Image: %s\n", cfg.Docker.Image)
	fmt.Printf("Dockerfile: %s\n", cfg.Docker.Dockerfile)
	fmt.Printf("Compose File: %s\n", cfg.Compose.File)
	fmt.Printf("Kubernetes Namespace: %s\n", cfg.Kubernetes.Namespace)
	fmt.Printf("Helm Chart: %s\n", cfg.Helm.Chart)
	fmt.Printf("CI Provider: %s\n", cfg.CI.Provider)
	fmt.Printf("Cloud Provider: %s\n", cfg.Cloud.Provider)
	fmt.Printf("Cloud Region: %s\n", cfg.Cloud.Region)

	return nil
}

// Infra manages infrastructure
func (c *CLI) Infra(args []string) error {
	if len(args) == 0 {
		fmt.Println("Usage: devops infra <plan|apply|destroy|init>")
		return nil
	}

	subCmd := args[0]

	switch subCmd {
	case "init":
		return c.initTerraform()
	case "plan":
		return c.runTerraform([]string{"plan"})
	case "apply":
		return c.runTerraform([]string{"apply"})
	case "destroy":
		fmt.Println("⚠️  This will destroy all infrastructure!")
		fmt.Print("   Type 'yes' to confirm: ")
		var confirm string
		fmt.Scanln(&confirm)
		if confirm != "yes" {
			fmt.Println("   Cancelled")
			return nil
		}
		return c.runTerraform([]string{"destroy"})
	default:
		fmt.Printf("Unknown infra command: %s\n", subCmd)
		return nil
	}
}

// initTerraform initializes Terraform
func (c *CLI) initTerraform() error {
	fmt.Println("🔧 Initializing Terraform...")

	// Create terraform directory
	if err := os.MkdirAll("terraform", 0755); err != nil {
		return fmt.Errorf("failed to create terraform directory: %w", err)
	}

	// Create main.tf
	mainTf := `terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

variable "aws_region" {
  description = "AWS region"
  type        = string
  default     = "us-west-2"
}

variable "environment" {
  description = "Environment name"
  type        = string
  default     = "development"
}

# VPC
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "\${var.environment}-vpc"
    Environment = var.environment
  }
}

# Subnet
resource "aws_subnet" "main" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "\${var.aws_region}a"
  map_public_ip_on_launch = true

  tags = {
    Name        = "\${var.environment}-subnet"
    Environment = var.environment
  }
}

# Internet Gateway
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name        = "\${var.environment}-igw"
    Environment = var.environment
  }
}

# Route Table
resource "aws_route_table" "main" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name        = "\${var.environment}-rt"
    Environment = var.environment
  }
}

resource "aws_route_table_association" "main" {
  subnet_id      = aws_subnet.main.id
  route_table_id = aws_route_table.main.id
}

# Security Group
resource "aws_security_group" "main" {
  name        = "\${var.environment}-sg"
  description = "Security group for \${var.environment}"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 8080
    to_port     = 8080
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name        = "\${var.environment}-sg"
    Environment = var.environment
  }
}

# ECS Cluster
resource "aws_ecs_cluster" "main" {
  name = "\${var.environment}-cluster"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }

  tags = {
    Name        = "\${var.environment}-ecs-cluster"
    Environment = var.environment
  }
}

# EKS Cluster
resource "aws_eks_cluster" "main" {
  name     = "\${var.environment}-eks"
  role_arn = aws_iam_role.eks_cluster.arn
  version  = "1.27"

  vpc_config {
    subnet_ids = [aws_subnet.main.id]
  }

  depends_on = [
    aws_iam_role_policy_attachment.eks_cluster_policy
  ]

  tags = {
    Name        = "\${var.environment}-eks"
    Environment = var.environment
  }
}

# IAM Role for EKS Cluster
resource "aws_iam_role" "eks_cluster" {
  name = "\${var.environment}-eks-cluster-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "eks.amazonaws.com"
      }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "eks_cluster_policy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.eks_cluster.name
}

# Outputs
output "vpc_id" {
  description = "VPC ID"
  value       = aws_vpc.main.id
}

output "subnet_id" {
  description = "Subnet ID"
  value       = aws_subnet.main.id
}

output "ecs_cluster_name" {
  description = "ECS Cluster Name"
  value       = aws_ecs_cluster.main.name
}

output "eks_cluster_name" {
  description = "EKS Cluster Name"
  value       = aws_eks_cluster.main.name
}

output "eks_cluster_endpoint" {
  description = "EKS Cluster Endpoint"
  value       = aws_eks_cluster.main.endpoint
}
`

	if err := os.WriteFile("terraform/main.tf", []byte(mainTf), 0644); err != nil {
		return fmt.Errorf("failed to create main.tf: %w", err)
	}

	// Create variables.tf
	varsTf := `variable "aws_region" {
  description = "AWS region for resources"
  type        = string
  default     = "us-west-2"
}

variable "environment" {
  description = "Environment name (development, staging, production)"
  type        = string
  default     = "development"
}
`

	if err := os.WriteFile("terraform/variables.tf", []byte(varsTf), 0644); err != nil {
		return fmt.Errorf("failed to create variables.tf: %w", err)
	}

	// Create outputs.tf
	outputsTf := `output "vpc_id" {
  description = "ID of the VPC"
  value       = aws_vpc.main.id
}

output "subnet_id" {
  description = "ID of the subnet"
  value       = aws_subnet.main.id
}

output "ecs_cluster_arn" {
  description = "ARN of the ECS Cluster"
  value       = aws_ecs_cluster.main.arn
}

output "eks_cluster_endpoint" {
  description = "Endpoint for EKS control plane"
  value       = aws_eks_cluster.main.endpoint
}
`

	if err := os.WriteFile("terraform/outputs.tf", []byte(outputsTf), 0644); err != nil {
		return fmt.Errorf("failed to create outputs.tf: %w", err)
	}

	// Run terraform init
	fmt.Println("📦 Running terraform init...")
	if err := c.runCommand("terraform", "init"); err != nil {
		fmt.Printf("⚠️  terraform init warning: %v\n", err)
	}

	fmt.Println("✅ Terraform initialized!")
	fmt.Println("   Created terraform/main.tf")
	fmt.Println("   Created terraform/variables.tf")
	fmt.Println("   Created terraform/outputs.tf")
	fmt.Println("\nNext steps:")
	fmt.Println("   1. Customize terraform/main.tf for your needs")
	fmt.Println("   2. Run 'devops infra plan' to preview changes")
	fmt.Println("   3. Run 'devops infra apply' to create infrastructure")

	return nil
}

// runTerraform runs Terraform commands
func (c *CLI) runTerraform(args []string) error {
	// Check if terraform directory exists
	if _, err := os.Stat("terraform"); os.IsNotExist(err) {
		return fmt.Errorf("terraform directory not found. Run 'devops infra init' first")
	}

	// Add auto-approve for non-interactive mode
	for _, arg := range args {
		if arg == "apply" || arg == "destroy" {
			args = append(args, "-auto-approve")
		}
	}

	// Change to terraform directory
	originalDir, _ := os.Getwd()
	os.Chdir("terraform")
	defer os.Chdir(originalDir)

	return c.runCommand("terraform", args...)
}

// CI manages CI/CD operations
func (c *CLI) CI(args []string) error {
	if len(args) == 0 {
		fmt.Println("Usage: devops ci <run|deploy|status|init>")
		return nil
	}

	subCmd := args[0]

	switch subCmd {
	case "init":
		return c.initCI()
	case "run":
		return c.runCI()
	case "deploy":
		return c.runCIDeploy()
	case "status":
		return c.checkCIStatus()
	default:
		fmt.Printf("Unknown ci command: %s\n", subCmd)
		return nil
	}
}

// initCI initializes CI/CD
func (c *CLI) initCI() error {
	fmt.Println("🔧 Initializing CI/CD...")

	// Create GitHub Actions workflow
	workflow := `.github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure kubectl
        uses: azure/k8s-set-context@v3
        with:
          kubeconfig: ${{ secrets.KUBE_CONFIG }}

      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/myapp app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
          kubectl rollout status deployment/myapp
`

	// Create directories
	os.MkdirAll(".github/workflows", 0755)

	if err := os.WriteFile(".github/workflows/deploy.yml", []byte(workflow), 0644); err != nil {
		return fmt.Errorf("failed to create workflow: %w", err)
	}

	fmt.Println("✅ CI/CD initialized!")
	fmt.Println("   Created .github/workflows/deploy.yml")
	fmt.Println("\nNext steps:")
	fmt.Println("   1. Add KUBE_CONFIG secret to GitHub")
	fmt.Println("   2. Customize the workflow for your needs")
	fmt.Println("   3. Push to trigger the pipeline")

	return nil
}

// runCI runs CI pipeline locally
func (c *CLI) runCI() error {
	fmt.Println("🚀 Running CI pipeline locally...")

	// Run tests
	fmt.Println("   Running tests...")
	if err := c.runCommand("go", "test", "./..."); err != nil {
		fmt.Println("⚠️  Tests failed or no Go tests found")
	}

	// Run lint
	fmt.Println("   Running linter...")
	if err := c.runCommand("golangci-lint", "run"); err != nil {
		fmt.Println("⚠️  Linting warnings")
	}

	// Build
	fmt.Println("   Building...")
	if err := c.runCommand("docker", "build", "-t", "myapp:ci", "."); err != nil {
		return fmt.Errorf("build failed: %w", err)
	}

	fmt.Println("✅ CI pipeline completed!")
	return nil
}

// runCIDeploy runs CI deployment
func (c *CLI) runCIDeploy() error {
	fmt.Println("🚀 Running CI deployment...")

	// Build and push
	fmt.Println("   Building image...")
	if err := c.Build([]string{"-t", "myapp:deploy"}); err != nil {
		return err
	}

	// Deploy
	fmt.Println("   Deploying...")
	return c.Deploy([]string{})
}

// checkCIStatus checks CI status
func (c *CLI) checkCIStatus() error {
	cfg, err := config.Load("devops.yml")
	if err != nil {
		cfg = config.Default()
	}

	switch cfg.CI.Provider {
	case "github":
		fmt.Println("📋 GitHub Actions Status:")
		return c.runCommand("gh", "run", "list")
	case "gitlab":
		fmt.Println("📋 GitLab CI Status:")
		return c.runCommand("glab", "ci", "list")
	default:
		fmt.Println("⚠️  No CI provider configured")
		return nil
	}
}

// Plugin manages plugins
func (c *CLI) Plugin(args []string) error {
	if len(args) == 0 {
		return c.listPlugins()
	}

	subCmd := args[0]

	switch subCmd {
	case "list":
		return c.listPlugins()
	case "install":
		if len(args) < 2 {
			fmt.Println("Usage: devops plugin install <name>")
			return nil
		}
		return c.installPlugin(args[1])
	case "uninstall":
		if len(args) < 2 {
			fmt.Println("Usage: devops plugin uninstall <name>")
			return nil
		}
		return c.uninstallPlugin(args[1])
	default:
		return c.listPlugins()
	}
}

// listPlugins lists available plugins
func (c *CLI) listPlugins() error {
	fmt.Println("🔌 Available Plugins:\n")

	plugins := []struct {
		name        string
		description string
		enabled     bool
	}{
		{"docker", "Docker and Docker Compose operations", true},
		{"kubernetes", "Kubernetes deployments with kubectl", true},
		{"helm", "Helm chart management", true},
		{"terraform", "Infrastructure as Code with Terraform", true},
		{"github", "GitHub Actions integration", true},
		{"gitlab", "GitLab CI integration", true},
		{"jenkins", "Jenkins pipeline support", true},
		{"aws", "Amazon Web Services integration", true},
		{"azure", "Microsoft Azure integration", true},
		{"gcp", "Google Cloud Platform integration", true},
	}

	for _, p := range plugins {
		status := "✅"
		if !p.enabled {
			status = "❌"
		}
		fmt.Printf("   %s [%s] %s\n", status, p.name, p.description)
	}

	return nil
}

// installPlugin installs a plugin
func (c *CLI) installPlugin(name string) error {
	fmt.Printf("📦 Installing plugin: %s\n", name)
	// Plugin installation would download and install the plugin
	fmt.Printf("✅ Plugin %s installed\n", name)
	return nil
}

// uninstallPlugin uninstalls a plugin
func (c *CLI) uninstallPlugin(name string) error {
	fmt.Printf("🗑️  Uninstalling plugin: %s\n", name)
	// Plugin uninstallation would remove the plugin
	fmt.Printf("✅ Plugin %s uninstalled\n", name)
	return nil
}

// runCompose runs docker-compose command
func (c *CLI) runCompose(args []string) error {
	return c.runCommand("docker", append([]string{"compose"}, args...)...)
}

// runCommand runs an external command
func (c *CLI) runCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin

	if err := cmd.Run(); err != nil {
		// Don't return error for optional commands
		return nil
	}
	return nil
}

// Helper functions for checking dependencies

func checkDocker() bool {
	_, err := exec.LookPath("docker")
	return err == nil
}

func checkDockerCompose() bool {
	// Check for docker compose (newer versions)
	_, err := exec.Command("docker", "compose", "version").Output()
	if err == nil {
		return true
	}
	// Check for docker-compose (older versions)
	_, err = exec.LookPath("docker-compose")
	return err == nil
}

func checkKubectl() bool {
	_, err := exec.LookPath("kubectl")
	return err == nil
}

func checkHelm() bool {
	_, err := exec.LookPath("helm")
	return err == nil
}

func checkTerraform() bool {
	_, err := exec.LookPath("terraform")
	return err == nil
}

func checkGit() bool {
	_, err := exec.LookPath("git")
	return err == nil
}

func checkGo() bool {
	_, err := exec.LookPath("go")
	return err == nil
}

func checkNode() bool {
	_, err := exec.LookPath("node")
	return err == nil
}

func checkPython() bool {
	_, err := exec.LookPath("python3")
	if err == nil {
		return true
	}
	_, err = exec.LookPath("python")
	return err == nil
}

func checkAWSCredentials() bool {
	home, _ := os.UserHomeDir()
	awsPath := filepath.Join(home, ".aws", "credentials")
	_, err := os.Stat(awsPath)
	return err == nil
}

func checkAzureCredentials() bool {
	_, err := exec.Command("az", "account", "show").Output()
	return err == nil
}

func checkGCPCredentials() bool {
	home, _ := os.UserHomeDir()
	gcpPath := filepath.Join(home, ".config", "gcloud", "credentials.json")
	_, err := os.Stat(gcpPath)
	return err == nil
}

// GetPlugin returns a registered plugin
func (c *CLI) GetPlugin(name string) (plugins.Plugin, bool) {
	p, ok := c.plugins[name]
	return p, ok
}

// GetPlugins returns all registered plugins
func (c *CLI) GetPlugins() map[string]plugins.Plugin {
	return c.plugins
}
