package generators

import (
	"context"
	"fmt"
	"regexp"
	"strings"

	"github.com/pkg/errors"
	analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
	"github.com/replicatedhq/troubleshoot/pkg/constants"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"k8s.io/klog/v2"
)

// AnalyzerGenerator generates analyzer specifications from requirements
type AnalyzerGenerator struct {
	templates  map[string]AnalyzerTemplate
	validators map[string]RequirementValidator
}

// AnalyzerTemplate defines how to generate analyzers for specific requirement types
type AnalyzerTemplate struct {
	Name        string
	Description string
	Category    string
	Priority    int
	Generator   func(ctx context.Context, req interface{}) ([]analyzer.AnalyzerSpec, error)
	Validator   func(req interface{}) error
}

// RequirementValidator validates requirement specifications
type RequirementValidator func(requirement interface{}) error

// GenerationOptions configures analyzer generation
type GenerationOptions struct {
	IncludeOptional bool
	Strict          bool
	DefaultPriority int
	CategoryFilter  []string
	CustomTemplates map[string]AnalyzerTemplate
}

// NewAnalyzerGenerator creates a new analyzer generator with default templates
func NewAnalyzerGenerator() *AnalyzerGenerator {
	g := &AnalyzerGenerator{
		templates:  make(map[string]AnalyzerTemplate),
		validators: make(map[string]RequirementValidator),
	}

	// Register default templates
	g.registerDefaultTemplates()
	g.registerDefaultValidators()

	return g
}

// GenerateAnalyzers creates analyzer specifications from requirements
func (g *AnalyzerGenerator) GenerateAnalyzers(ctx context.Context, requirements *analyzer.RequirementSpec, opts *GenerationOptions) ([]analyzer.AnalyzerSpec, error) {
	ctx, span := otel.Tracer(constants.LIB_TRACER_NAME).Start(ctx, "AnalyzerGenerator.GenerateAnalyzers")
	defer span.End()

	if requirements == nil {
		return nil, errors.New("requirements cannot be nil")
	}

	if opts == nil {
		opts = &GenerationOptions{
			IncludeOptional: true,
			DefaultPriority: 5,
		}
	}

	var allSpecs []analyzer.AnalyzerSpec

	// Generate Kubernetes version analyzers
	if specs, err := g.generateKubernetesAnalyzers(ctx, &requirements.Spec.Kubernetes, opts); err == nil {
		allSpecs = append(allSpecs, specs...)
	} else {
		klog.Warningf("Failed to generate Kubernetes analyzers: %v", err)
	}

	// Generate resource requirement analyzers
	if specs, err := g.generateResourceAnalyzers(ctx, &requirements.Spec.Resources, opts); err == nil {
		allSpecs = append(allSpecs, specs...)
	} else {
		klog.Warningf("Failed to generate resource analyzers: %v", err)
	}

	// Generate storage requirement analyzers
	if specs, err := g.generateStorageAnalyzers(ctx, &requirements.Spec.Storage, opts); err == nil {
		allSpecs = append(allSpecs, specs...)
	} else {
		klog.Warningf("Failed to generate storage analyzers: %v", err)
	}

	// Generate network requirement analyzers
	if specs, err := g.generateNetworkAnalyzers(ctx, &requirements.Spec.Network, opts); err == nil {
		allSpecs = append(allSpecs, specs...)
	} else {
		klog.Warningf("Failed to generate network analyzers: %v", err)
	}

	// Generate custom analyzers
	for _, customReq := range requirements.Spec.Custom {
		if specs, err := g.generateCustomAnalyzers(ctx, &customReq, opts); err == nil {
			allSpecs = append(allSpecs, specs...)
		} else {
			klog.Warningf("Failed to generate custom analyzer %s: %v", customReq.Name, err)
		}
	}

	// Apply category filtering if specified
	if len(opts.CategoryFilter) > 0 {
		allSpecs = g.filterByCategory(allSpecs, opts.CategoryFilter)
	}

	// Sort by priority (higher priority first)
	g.sortByPriority(allSpecs)

	span.SetAttributes(
		attribute.Int("total_generated", len(allSpecs)),
		attribute.String("requirements_name", requirements.Metadata.Name),
		attribute.Bool("include_optional", opts.IncludeOptional),
	)

	return allSpecs, nil
}

// generateKubernetesAnalyzers creates analyzers for Kubernetes requirements
func (g *AnalyzerGenerator) generateKubernetesAnalyzers(ctx context.Context, req *analyzer.KubernetesRequirements, opts *GenerationOptions) ([]analyzer.AnalyzerSpec, error) {
	var specs []analyzer.AnalyzerSpec

	// Kubernetes version check analyzer
	if req.MinVersion != "" || req.MaxVersion != "" {
		spec := analyzer.AnalyzerSpec{
			Name:     "kubernetes-version-requirement",
			Type:     "cluster",
			Category: "kubernetes",
			Priority: 10,
			Config: map[string]interface{}{
				"checkName":  "Kubernetes Version Check",
				"minVersion": req.MinVersion,
				"maxVersion": req.MaxVersion,
				"outcomes":   g.generateVersionOutcomes(req.MinVersion, req.MaxVersion),
			},
		}
		specs = append(specs, spec)
	}

	// Required components analyzer
	if len(req.Required) > 0 {
		spec := analyzer.AnalyzerSpec{
			Name:     "kubernetes-components-required",
			Type:     "cluster",
			Category: "kubernetes",
			Priority: 9,
			Config: map[string]interface{}{
				"checkName": "Required Components Check",
				"required":  req.Required,
				"outcomes":  g.generateComponentOutcomes(req.Required, true),
			},
		}
		specs = append(specs, spec)
	}

	// Forbidden components analyzer
	if len(req.Forbidden) > 0 {
		spec := analyzer.AnalyzerSpec{
			Name:     "kubernetes-components-forbidden",
			Type:     "cluster",
			Category: "kubernetes",
			Priority: 8,
			Config: map[string]interface{}{
				"checkName": "Forbidden Components Check",
				"forbidden": req.Forbidden,
				"outcomes":  g.generateComponentOutcomes(req.Forbidden, false),
			},
		}
		specs = append(specs, spec)
	}

	return specs, nil
}

// generateResourceAnalyzers creates analyzers for resource requirements
func (g *AnalyzerGenerator) generateResourceAnalyzers(ctx context.Context, req *analyzer.ResourceRequirements, opts *GenerationOptions) ([]analyzer.AnalyzerSpec, error) {
	var specs []analyzer.AnalyzerSpec

	// Node resources analyzer
	if req.CPU.Min != "" || req.Memory.Min != "" || req.Disk.Min != "" {
		spec := analyzer.AnalyzerSpec{
			Name:     "node-resources-requirement",
			Type:     "resources",
			Category: "capacity",
			Priority: 9,
			Config: map[string]interface{}{
				"checkName": "Node Resources Check",
				"cpu":       req.CPU,
				"memory":    req.Memory,
				"disk":      req.Disk,
				"outcomes":  g.generateResourceOutcomes(req),
			},
		}
		specs = append(specs, spec)
	}

	// Cluster capacity analyzer
	if req.CPU.Min != "" || req.Memory.Min != "" {
		spec := analyzer.AnalyzerSpec{
			Name:     "cluster-capacity-requirement",
			Type:     "resources",
			Category: "capacity",
			Priority: 8,
			Config: map[string]interface{}{
				"checkName":    "Cluster Capacity Check",
				"requirements": req,
				"outcomes":     g.generateClusterCapacityOutcomes(req),
			},
		}
		specs = append(specs, spec)
	}

	return specs, nil
}

// generateStorageAnalyzers creates analyzers for storage requirements
func (g *AnalyzerGenerator) generateStorageAnalyzers(ctx context.Context, req *analyzer.StorageRequirements, opts *GenerationOptions) ([]analyzer.AnalyzerSpec, error) {
	var specs []analyzer.AnalyzerSpec

	// Storage class analyzer
	if len(req.Classes) > 0 {
		spec := analyzer.AnalyzerSpec{
			Name:     "storage-class-requirement",
			Type:     "storage",
			Category: "storage",
			Priority: 8,
			Config: map[string]interface{}{
				"checkName":    "Storage Class Check",
				"storageClass": req.Classes[0], // Use first class as primary
				"outcomes":     g.generateStorageClassOutcomes(req.Classes),
			},
		}
		specs = append(specs, spec)
	}

	// Persistent volume analyzer
	if req.MinCapacity != "" {
		spec := analyzer.AnalyzerSpec{
			Name:     "persistent-volume-requirement",
			Type:     "storage",
			Category: "storage",
			Priority: 7,
			Config: map[string]interface{}{
				"checkName":   "Persistent Volume Capacity Check",
				"minCapacity": req.MinCapacity,
				"accessModes": req.AccessModes,
				"outcomes":    g.generatePVOutcomes(req),
			},
		}
		specs = append(specs, spec)
	}

	return specs, nil
}

// generateNetworkAnalyzers creates analyzers for network requirements
func (g *AnalyzerGenerator) generateNetworkAnalyzers(ctx context.Context, req *analyzer.NetworkRequirements, opts *GenerationOptions) ([]analyzer.AnalyzerSpec, error) {
	var specs []analyzer.AnalyzerSpec

	// Port connectivity analyzer
	for _, port := range req.Ports {
		spec := analyzer.AnalyzerSpec{
			Name:     fmt.Sprintf("port-connectivity-%d", port.Port),
			Type:     "network",
			Category: "networking",
			Priority: 7,
			Config: map[string]interface{}{
				"checkName": fmt.Sprintf("Port %d Connectivity Check", port.Port),
				"port":      port.Port,
				"protocol":  port.Protocol,
				"required":  port.Required,
				"outcomes":  g.generatePortOutcomes(port),
			},
		}
		specs = append(specs, spec)
	}

	// General connectivity analyzer
	if len(req.Connectivity) > 0 {
		spec := analyzer.AnalyzerSpec{
			Name:     "network-connectivity-requirement",
			Type:     "network",
			Category: "networking",
			Priority: 6,
			Config: map[string]interface{}{
				"checkName":    "Network Connectivity Check",
				"connectivity": req.Connectivity,
				"outcomes":     g.generateConnectivityOutcomes(req.Connectivity),
			},
		}
		specs = append(specs, spec)
	}

	return specs, nil
}

// generateCustomAnalyzers creates analyzers for custom requirements
func (g *AnalyzerGenerator) generateCustomAnalyzers(ctx context.Context, req *analyzer.CustomRequirement, opts *GenerationOptions) ([]analyzer.AnalyzerSpec, error) {
	var specs []analyzer.AnalyzerSpec

	// Check if we have a template for this custom type
	template, exists := g.templates[req.Type]
	if exists {
		customSpecs, err := template.Generator(ctx, req)
		if err != nil {
			return nil, errors.Wrapf(err, "failed to generate custom analyzer %s", req.Name)
		}
		specs = append(specs, customSpecs...)
	} else {
		// Generic custom analyzer
		spec := analyzer.AnalyzerSpec{
			Name:     req.Name,
			Type:     req.Type,
			Category: "custom",
			Priority: opts.DefaultPriority,
			Config: map[string]interface{}{
				"checkName": req.Name,
				"condition": req.Condition,
				"context":   req.Context,
				"outcomes":  g.generateCustomOutcomes(req),
			},
		}
		specs = append(specs, spec)
	}

	return specs, nil
}

// Outcome generation methods

func (g *AnalyzerGenerator) generateVersionOutcomes(minVersion, maxVersion string) []map[string]interface{} {
	var outcomes []map[string]interface{}

	// Pass condition
	passCondition := "true"
	if minVersion != "" && maxVersion != "" {
		passCondition = fmt.Sprintf(">= %s && < %s", minVersion, maxVersion)
	} else if minVersion != "" {
		passCondition = fmt.Sprintf(">= %s", minVersion)
	} else if maxVersion != "" {
		passCondition = fmt.Sprintf("< %s", maxVersion)
	}

	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"when":    passCondition,
			"message": "Kubernetes version meets requirements",
		},
	})

	// Fail condition
	if minVersion != "" {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf("< %s", minVersion),
				"message": fmt.Sprintf("Kubernetes version is below minimum required version %s", minVersion),
			},
		})
	}

	if maxVersion != "" {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf(">= %s", maxVersion),
				"message": fmt.Sprintf("Kubernetes version is at or above maximum supported version %s", maxVersion),
			},
		})
	}

	return outcomes
}

func (g *AnalyzerGenerator) generateComponentOutcomes(components []string, required bool) []map[string]interface{} {
	var outcomes []map[string]interface{}

	for _, component := range components {
		if required {
			outcomes = append(outcomes, map[string]interface{}{
				"fail": map[string]interface{}{
					"when":    fmt.Sprintf("missing %s", component),
					"message": fmt.Sprintf("Required component %s is missing", component),
				},
			})
		} else {
			outcomes = append(outcomes, map[string]interface{}{
				"fail": map[string]interface{}{
					"when":    fmt.Sprintf("present %s", component),
					"message": fmt.Sprintf("Forbidden component %s is present", component),
				},
			})
		}
	}

	// Default pass outcome
	if required {
		outcomes = append(outcomes, map[string]interface{}{
			"pass": map[string]interface{}{
				"message": "All required components are present",
			},
		})
	} else {
		outcomes = append(outcomes, map[string]interface{}{
			"pass": map[string]interface{}{
				"message": "No forbidden components are present",
			},
		})
	}

	return outcomes
}

func (g *AnalyzerGenerator) generateResourceOutcomes(req *analyzer.ResourceRequirements) []map[string]interface{} {
	var outcomes []map[string]interface{}

	// CPU requirements
	if req.CPU.Min != "" {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf("cpu < %s", req.CPU.Min),
				"message": fmt.Sprintf("Insufficient CPU resources. Minimum required: %s", req.CPU.Min),
			},
		})
	}

	// Memory requirements
	if req.Memory.Min != "" {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf("memory < %s", req.Memory.Min),
				"message": fmt.Sprintf("Insufficient memory resources. Minimum required: %s", req.Memory.Min),
			},
		})
	}

	// Disk requirements
	if req.Disk.Min != "" {
		outcomes = append(outcomes, map[string]interface{}{
			"warn": map[string]interface{}{
				"when":    fmt.Sprintf("disk < %s", req.Disk.Min),
				"message": fmt.Sprintf("Low disk space. Minimum recommended: %s", req.Disk.Min),
			},
		})
	}

	// Pass condition
	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"message": "Resource requirements are satisfied",
		},
	})

	return outcomes
}

func (g *AnalyzerGenerator) generateClusterCapacityOutcomes(req *analyzer.ResourceRequirements) []map[string]interface{} {
	var outcomes []map[string]interface{}

	outcomes = append(outcomes, map[string]interface{}{
		"fail": map[string]interface{}{
			"when":    "clusterCapacity < requirements",
			"message": "Cluster does not have sufficient capacity to meet requirements",
		},
	})

	outcomes = append(outcomes, map[string]interface{}{
		"warn": map[string]interface{}{
			"when":    "clusterCapacity < requirements * 1.2",
			"message": "Cluster capacity is close to requirements. Consider adding buffer capacity",
		},
	})

	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"message": "Cluster has sufficient capacity for requirements",
		},
	})

	return outcomes
}

func (g *AnalyzerGenerator) generateStorageClassOutcomes(classes []string) []map[string]interface{} {
	var outcomes []map[string]interface{}

	for _, class := range classes {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf("storageClass == %s && !exists", class),
				"message": fmt.Sprintf("Required storage class %s does not exist", class),
			},
		})
	}

	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"message": "Required storage classes are available",
		},
	})

	return outcomes
}

func (g *AnalyzerGenerator) generatePVOutcomes(req *analyzer.StorageRequirements) []map[string]interface{} {
	var outcomes []map[string]interface{}

	outcomes = append(outcomes, map[string]interface{}{
		"fail": map[string]interface{}{
			"when":    fmt.Sprintf("availableCapacity < %s", req.MinCapacity),
			"message": fmt.Sprintf("Insufficient storage capacity. Minimum required: %s", req.MinCapacity),
		},
	})

	if len(req.AccessModes) > 0 {
		for _, mode := range req.AccessModes {
			outcomes = append(outcomes, map[string]interface{}{
				"warn": map[string]interface{}{
					"when":    fmt.Sprintf("!accessMode.%s", mode),
					"message": fmt.Sprintf("Access mode %s may not be supported", mode),
				},
			})
		}
	}

	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"message": "Storage requirements are satisfied",
		},
	})

	return outcomes
}

func (g *AnalyzerGenerator) generatePortOutcomes(port analyzer.PortRequirement) []map[string]interface{} {
	var outcomes []map[string]interface{}

	if port.Required {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf("port.%d.%s == false", port.Port, strings.ToLower(port.Protocol)),
				"message": fmt.Sprintf("Required port %d/%s is not accessible", port.Port, port.Protocol),
			},
		})
	}

	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"when":    fmt.Sprintf("port.%d.%s == true", port.Port, strings.ToLower(port.Protocol)),
			"message": fmt.Sprintf("Port %d/%s is accessible", port.Port, port.Protocol),
		},
	})

	return outcomes
}

func (g *AnalyzerGenerator) generateConnectivityOutcomes(connectivity []string) []map[string]interface{} {
	var outcomes []map[string]interface{}

	for _, target := range connectivity {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf("connectivity.%s == false", target),
				"message": fmt.Sprintf("Cannot reach %s", target),
			},
		})
	}

	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"message": "All connectivity requirements are satisfied",
		},
	})

	return outcomes
}

func (g *AnalyzerGenerator) generateCustomOutcomes(req *analyzer.CustomRequirement) []map[string]interface{} {
	var outcomes []map[string]interface{}

	// Parse the condition and generate appropriate outcomes
	condition := req.Condition
	if condition == "" {
		condition = "true"
	}

	// Basic pattern matching for common conditions
	if strings.Contains(condition, ">=") || strings.Contains(condition, ">") {
		outcomes = append(outcomes, map[string]interface{}{
			"fail": map[string]interface{}{
				"when":    fmt.Sprintf("!(%s)", condition),
				"message": fmt.Sprintf("Custom requirement '%s' not met", req.Name),
			},
		})
	}

	outcomes = append(outcomes, map[string]interface{}{
		"pass": map[string]interface{}{
			"when":    condition,
			"message": fmt.Sprintf("Custom requirement '%s' is satisfied", req.Name),
		},
	})

	return outcomes
}

// Helper methods

func (g *AnalyzerGenerator) filterByCategory(specs []analyzer.AnalyzerSpec, categories []string) []analyzer.AnalyzerSpec {
	if len(categories) == 0 {
		return specs
	}

	var filtered []analyzer.AnalyzerSpec
	categorySet := make(map[string]bool)
	for _, cat := range categories {
		categorySet[cat] = true
	}

	for _, spec := range specs {
		if categorySet[spec.Category] {
			filtered = append(filtered, spec)
		}
	}

	return filtered
}

func (g *AnalyzerGenerator) sortByPriority(specs []analyzer.AnalyzerSpec) {
	// Simple bubble sort by priority (higher first)
	n := len(specs)
	for i := 0; i < n-1; i++ {
		for j := 0; j < n-1-i; j++ {
			if specs[j].Priority < specs[j+1].Priority {
				specs[j], specs[j+1] = specs[j+1], specs[j]
			}
		}
	}
}

// Template and validator registration

func (g *AnalyzerGenerator) registerDefaultTemplates() {
	// Register built-in analyzer templates
	g.templates["database"] = AnalyzerTemplate{
		Name:        "Database Analyzer",
		Description: "Analyzes database connectivity and requirements",
		Category:    "database",
		Priority:    7,
		Generator:   g.generateDatabaseAnalyzer,
		Validator:   g.validateDatabaseRequirement,
	}

	g.templates["api"] = AnalyzerTemplate{
		Name:        "API Analyzer",
		Description: "Analyzes API endpoint connectivity and requirements",
		Category:    "api",
		Priority:    6,
		Generator:   g.generateAPIAnalyzer,
		Validator:   g.validateAPIRequirement,
	}
}

func (g *AnalyzerGenerator) registerDefaultValidators() {
	g.validators["version"] = func(req interface{}) error {
		// Validate version format
		versionStr, ok := req.(string)
		if !ok {
			return errors.New("version must be a string")
		}

		// Basic semantic version validation
		versionRegex := regexp.MustCompile(`^v?\d+\.\d+(\.\d+)?(-.*)?$`)
		if !versionRegex.MatchString(versionStr) {
			return errors.Errorf("invalid version format: %s", versionStr)
		}

		return nil
	}

	g.validators["resource"] = func(req interface{}) error {
		// Validate resource specifications
		resourceStr, ok := req.(string)
		if !ok {
			return errors.New("resource must be a string")
		}

		// Validate resource format (e.g., "100m", "1Gi", "500Mi")
		resourceRegex := regexp.MustCompile(`^(\d+(\.\d+)?)(m|Mi|Gi|Ti|Ki|k|M|G|T)?$`)
		if !resourceRegex.MatchString(resourceStr) {
			return errors.Errorf("invalid resource format: %s", resourceStr)
		}

		return nil
	}
}

// Custom analyzer generators

func (g *AnalyzerGenerator) generateDatabaseAnalyzer(ctx context.Context, req interface{}) ([]analyzer.AnalyzerSpec, error) {
	customReq, ok := req.(*analyzer.CustomRequirement)
	if !ok {
		return nil, errors.New("invalid database requirement type")
	}

	spec := analyzer.AnalyzerSpec{
		Name:     fmt.Sprintf("database-%s", customReq.Name),
		Type:     "database",
		Category: "database",
		Priority: 7,
		Config: map[string]interface{}{
			"checkName": fmt.Sprintf("Database %s Check", customReq.Name),
			"uri":       customReq.Context["uri"],
			"timeout":   "10s",
			"outcomes": []map[string]interface{}{
				{
					"fail": map[string]interface{}{
						"when":    "error",
						"message": "Database connection failed",
					},
				},
				{
					"pass": map[string]interface{}{
						"message": "Database connection successful",
					},
				},
			},
		},
	}

	return []analyzer.AnalyzerSpec{spec}, nil
}

func (g *AnalyzerGenerator) generateAPIAnalyzer(ctx context.Context, req interface{}) ([]analyzer.AnalyzerSpec, error) {
	customReq, ok := req.(*analyzer.CustomRequirement)
	if !ok {
		return nil, errors.New("invalid API requirement type")
	}

	spec := analyzer.AnalyzerSpec{
		Name:     fmt.Sprintf("api-%s", customReq.Name),
		Type:     "http",
		Category: "api",
		Priority: 6,
		Config: map[string]interface{}{
			"checkName": fmt.Sprintf("API %s Check", customReq.Name),
			"get": map[string]interface{}{
				"url": customReq.Context["url"],
			},
			"outcomes": []map[string]interface{}{
				{
					"fail": map[string]interface{}{
						"when":    "status != 200",
						"message": "API endpoint is not accessible",
					},
				},
				{
					"pass": map[string]interface{}{
						"when":    "status == 200",
						"message": "API endpoint is accessible",
					},
				},
			},
		},
	}

	return []analyzer.AnalyzerSpec{spec}, nil
}

// Custom requirement validators

func (g *AnalyzerGenerator) validateDatabaseRequirement(req interface{}) error {
	customReq, ok := req.(*analyzer.CustomRequirement)
	if !ok {
		return errors.New("invalid requirement type")
	}

	if customReq.Context == nil {
		return errors.New("database requirement must have context")
	}

	if _, exists := customReq.Context["uri"]; !exists {
		return errors.New("database requirement must specify 'uri' in context")
	}

	return nil
}

func (g *AnalyzerGenerator) validateAPIRequirement(req interface{}) error {
	customReq, ok := req.(*analyzer.CustomRequirement)
	if !ok {
		return errors.New("invalid requirement type")
	}

	if customReq.Context == nil {
		return errors.New("API requirement must have context")
	}

	if _, exists := customReq.Context["url"]; !exists {
		return errors.New("API requirement must specify 'url' in context")
	}

	return nil
}

// RegisterTemplate registers a custom analyzer template
func (g *AnalyzerGenerator) RegisterTemplate(name string, template AnalyzerTemplate) error {
	if name == "" {
		return errors.New("template name cannot be empty")
	}

	if template.Generator == nil {
		return errors.New("template generator cannot be nil")
	}

	g.templates[name] = template
	return nil
}

// RegisterValidator registers a custom requirement validator
func (g *AnalyzerGenerator) RegisterValidator(name string, validator RequirementValidator) error {
	if name == "" {
		return errors.New("validator name cannot be empty")
	}

	if validator == nil {
		return errors.New("validator cannot be nil")
	}

	g.validators[name] = validator
	return nil
}

// ValidateRequirements validates a requirement specification
func (g *AnalyzerGenerator) ValidateRequirements(ctx context.Context, requirements *analyzer.RequirementSpec) error {
	if requirements == nil {
		return errors.New("requirements cannot be nil")
	}

	// Validate Kubernetes requirements
	if err := g.validateKubernetesRequirements(&requirements.Spec.Kubernetes); err != nil {
		return errors.Wrap(err, "invalid Kubernetes requirements")
	}

	// Validate resource requirements
	if err := g.validateResourceRequirements(&requirements.Spec.Resources); err != nil {
		return errors.Wrap(err, "invalid resource requirements")
	}

	// Validate storage requirements
	if err := g.validateStorageRequirements(&requirements.Spec.Storage); err != nil {
		return errors.Wrap(err, "invalid storage requirements")
	}

	// Validate network requirements
	if err := g.validateNetworkRequirements(&requirements.Spec.Network); err != nil {
		return errors.Wrap(err, "invalid network requirements")
	}

	// Validate custom requirements
	for i, customReq := range requirements.Spec.Custom {
		if err := g.validateCustomRequirement(&customReq); err != nil {
			return errors.Wrapf(err, "invalid custom requirement at index %d", i)
		}
	}

	return nil
}

func (g *AnalyzerGenerator) validateKubernetesRequirements(req *analyzer.KubernetesRequirements) error {
	if req.MinVersion != "" {
		if err := g.validators["version"](req.MinVersion); err != nil {
			return errors.Wrap(err, "invalid minVersion")
		}
	}

	if req.MaxVersion != "" {
		if err := g.validators["version"](req.MaxVersion); err != nil {
			return errors.Wrap(err, "invalid maxVersion")
		}
	}

	return nil
}

func (g *AnalyzerGenerator) validateResourceRequirements(req *analyzer.ResourceRequirements) error {
	if req.CPU.Min != "" {
		if err := g.validators["resource"](req.CPU.Min); err != nil {
			return errors.Wrap(err, "invalid CPU minimum")
		}
	}

	if req.Memory.Min != "" {
		if err := g.validators["resource"](req.Memory.Min); err != nil {
			return errors.Wrap(err, "invalid memory minimum")
		}
	}

	if req.Disk.Min != "" {
		if err := g.validators["resource"](req.Disk.Min); err != nil {
			return errors.Wrap(err, "invalid disk minimum")
		}
	}

	return nil
}

func (g *AnalyzerGenerator) validateStorageRequirements(req *analyzer.StorageRequirements) error {
	if req.MinCapacity != "" {
		if err := g.validators["resource"](req.MinCapacity); err != nil {
			return errors.Wrap(err, "invalid minCapacity")
		}
	}

	// Validate access modes
	validAccessModes := map[string]bool{
		"ReadWriteOnce": true,
		"ReadOnlyMany":  true,
		"ReadWriteMany": true,
	}

	for _, mode := range req.AccessModes {
		if !validAccessModes[mode] {
			return errors.Errorf("invalid access mode: %s", mode)
		}
	}

	return nil
}

func (g *AnalyzerGenerator) validateNetworkRequirements(req *analyzer.NetworkRequirements) error {
	for _, port := range req.Ports {
		if port.Port <= 0 || port.Port > 65535 {
			return errors.Errorf("invalid port number: %d", port.Port)
		}

		validProtocols := map[string]bool{
			"TCP": true,
			"UDP": true,
		}

		if port.Protocol != "" && !validProtocols[strings.ToUpper(port.Protocol)] {
			return errors.Errorf("invalid protocol: %s", port.Protocol)
		}
	}

	return nil
}

func (g *AnalyzerGenerator) validateCustomRequirement(req *analyzer.CustomRequirement) error {
	if req.Name == "" {
		return errors.New("custom requirement name cannot be empty")
	}

	if req.Type == "" {
		return errors.New("custom requirement type cannot be empty")
	}

	// Check if we have a specific validator for this type
	if validator, exists := g.validators[req.Type]; exists {
		return validator(req)
	}

	// Check if we have a template with validator for this type
	if template, exists := g.templates[req.Type]; exists && template.Validator != nil {
		return template.Validator(req)
	}

	return nil
}
