package ux

import (
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

// Validator provides input validation functionality
type Validator struct {
	verbose bool
}

// NewValidator creates a new validator
func NewValidator(verbose bool) *Validator {
	return &Validator{verbose: verbose}
}

// ValidationResult represents the result of a validation
type ValidationResult struct {
	Valid   bool
	Message string
	Suggestions []string
}

// ValidateImageReference validates a container image reference
func (v *Validator) ValidateImageReference(imageRef string) *ValidationResult {
	if imageRef == "" {
		return &ValidationResult{
			Valid:   false,
			Message: "Image reference cannot be empty",
			Suggestions: []string{
				"Provide a valid container image reference",
				"Example: git.raines.xyz/particle-os/debian-bootc:latest",
				"Example: docker.io/debian:bookworm-slim",
			},
		}
	}

	// Basic validation for image reference format
	// Should contain at least one colon or slash
	if !strings.Contains(imageRef, ":") && !strings.Contains(imageRef, "/") {
		return &ValidationResult{
			Valid:   false,
			Message: "Invalid image reference format",
			Suggestions: []string{
				"Image reference should contain registry, namespace, and tag",
				"Example: registry.example.com/namespace/image:tag",
				"Example: image:tag",
			},
		}
	}

	// Check for valid characters (allow hyphens in addition to other valid chars)
	validChars := regexp.MustCompile(`^[a-zA-Z0-9._/:+-]+$`)
	if !validChars.MatchString(imageRef) {
		return &ValidationResult{
			Valid:   false,
			Message: "Image reference contains invalid characters",
			Suggestions: []string{
				"Use only alphanumeric characters, dots, underscores, slashes, hyphens, and colons",
				"Example: git.raines.xyz/particle-os/debian-bootc:latest",
			},
		}
	}

	return &ValidationResult{Valid: true}
}

// ValidateImageTypes validates image type specifications
func (v *Validator) ValidateImageTypes(imageTypes []string) *ValidationResult {
	if len(imageTypes) == 0 {
		return &ValidationResult{
			Valid:   false,
			Message: "At least one image type must be specified",
			Suggestions: []string{
				"Specify one or more image types: qcow2, ami, vmdk, raw, debian-installer, calamares",
				"Example: --type qcow2 --type ami",
			},
		}
	}

	validTypes := map[string]bool{
		"qcow2":            true,
		"ami":              true,
		"vmdk":             true,
		"raw":              true,
		"debian-installer": true,
		"calamares":        true,
	}

	var invalidTypes []string
	for _, imgType := range imageTypes {
		if !validTypes[imgType] {
			invalidTypes = append(invalidTypes, imgType)
		}
	}

	if len(invalidTypes) > 0 {
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("Invalid image types: %s", strings.Join(invalidTypes, ", ")),
			Suggestions: []string{
				"Supported image types: qcow2, ami, vmdk, raw, debian-installer, calamares",
				"Check spelling and case sensitivity",
			},
		}
	}

	return &ValidationResult{Valid: true}
}

// ValidateArchitecture validates target architecture
func (v *Validator) ValidateArchitecture(arch string) *ValidationResult {
	if arch == "" {
		return &ValidationResult{
			Valid:   false,
			Message: "Target architecture cannot be empty",
			Suggestions: []string{
				"Specify a valid architecture: amd64, arm64, armhf, ppc64el, s390x",
				"Example: --target-arch amd64",
			},
		}
	}

	validArchs := map[string]bool{
		"amd64":  true,
		"arm64":  true,
		"armhf":  true,
		"ppc64el": true,
		"s390x":  true,
	}

	if !validArchs[arch] {
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("Unsupported architecture: %s", arch),
			Suggestions: []string{
				"Supported architectures: amd64, arm64, armhf, ppc64el, s390x",
				"Use --target-arch amd64 for x86_64 systems",
			},
		}
	}

	return &ValidationResult{Valid: true}
}

// ValidateRootfsType validates root filesystem type
func (v *Validator) ValidateRootfsType(rootfsType string) *ValidationResult {
	if rootfsType == "" {
		// Empty is valid (will use default)
		return &ValidationResult{Valid: true}
	}

	validTypes := map[string]bool{
		"ext4":  true,
		"xfs":   true,
		"btrfs": true,
	}

	if !validTypes[rootfsType] {
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("Unsupported root filesystem type: %s", rootfsType),
			Suggestions: []string{
				"Supported filesystem types: ext4, xfs, btrfs",
				"Leave empty to use default (ext4)",
			},
		}
	}

	return &ValidationResult{Valid: true}
}

// ValidateDirectory validates a directory path
func (v *Validator) ValidateDirectory(path, purpose string) *ValidationResult {
	if path == "" {
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("%s path cannot be empty", purpose),
			Suggestions: []string{
				fmt.Sprintf("Specify a valid directory path for %s", purpose),
				"Use absolute or relative paths",
			},
		}
	}

	// Check if path exists and is a directory
	info, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			// Try to create the directory
			if err := os.MkdirAll(path, 0755); err != nil {
				return &ValidationResult{
					Valid:   false,
					Message: fmt.Sprintf("Cannot create %s directory: %v", purpose, err),
					Suggestions: []string{
						"Check parent directory permissions",
						"Use a different directory path",
						"Run with appropriate permissions",
					},
				}
			}
			return &ValidationResult{Valid: true}
		}
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("Cannot access %s directory: %v", purpose, err),
			Suggestions: []string{
				"Check directory permissions",
				"Ensure the path is accessible",
			},
		}
	}

	if !info.IsDir() {
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("%s path is not a directory: %s", purpose, path),
			Suggestions: []string{
				"Specify a directory path, not a file",
				"Check the path exists and is a directory",
			},
		}
	}

	return &ValidationResult{Valid: true}
}

// ValidateConfigFile validates a configuration file path
func (v *Validator) ValidateConfigFile(configPath string) *ValidationResult {
	if configPath == "" {
		// Empty is valid (will use default)
		return &ValidationResult{Valid: true}
	}

	// Check if file exists
	info, err := os.Stat(configPath)
	if err != nil {
		if os.IsNotExist(err) {
			return &ValidationResult{
				Valid:   false,
				Message: fmt.Sprintf("Configuration file not found: %s", configPath),
				Suggestions: []string{
					"Check the file path is correct",
					"Create a configuration file at the specified path",
					"Leave empty to use default configuration",
				},
			}
		}
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("Cannot access configuration file: %v", err),
			Suggestions: []string{
				"Check file permissions",
				"Ensure the file is accessible",
			},
		}
	}

	if info.IsDir() {
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("Configuration path is a directory, not a file: %s", configPath),
			Suggestions: []string{
				"Specify a file path, not a directory",
				"Example: .config/registry.yaml",
			},
		}
	}

	// Check file extension
	ext := strings.ToLower(filepath.Ext(configPath))
	if ext != ".yaml" && ext != ".yml" {
		return &ValidationResult{
			Valid:   false,
			Message: fmt.Sprintf("Configuration file should be YAML format: %s", configPath),
			Suggestions: []string{
				"Use .yaml or .yml extension",
				"Example: .config/registry.yaml",
			},
		}
	}

	return &ValidationResult{Valid: true}
}

// ValidateDistroDefPath validates distribution definition path
func (v *Validator) ValidateDistroDefPath(path string) *ValidationResult {
	if path == "" {
		return &ValidationResult{
			Valid:   false,
			Message: "Distribution definition path cannot be empty",
			Suggestions: []string{
				"Specify a valid directory path containing package definitions",
				"Example: ./data/defs",
			},
		}
	}

	return v.ValidateDirectory(path, "distribution definition")
}

// PrintValidationResult prints validation results with suggestions
func (v *Validator) PrintValidationResult(result *ValidationResult) {
	if result.Valid {
		if v.verbose {
			PrintInfo(os.Stdout, "Validation passed")
		}
		return
	}

	PrintError(os.Stdout, result.Message)
	
	if len(result.Suggestions) > 0 {
		fmt.Println("💡 Suggestions:")
		for _, suggestion := range result.Suggestions {
			fmt.Printf("   • %s\n", suggestion)
		}
	}
}
