package persona

import (
	"slices"

	cperr "github.com/tidbcloud/controlplane9/internal/errors"
)

// Validate checks that the persona's structure is internally consistent.
//   - persona name is non-empty
//   - no service is duplicated within real or within stub
//   - no service appears in both real and stub
//   - capabilities are from ValidCapabilities
//   - clouds are from ValidClouds
func Validate(p *Persona) error {
	if p == nil {
		return cperr.New(cperr.CategoryConfig, "persona is nil")
	}
	if p.Persona == "" {
		return cperr.New(cperr.CategoryConfig, "persona.persona is required")
	}

	seen := make(map[string]string, len(p.Real)+len(p.Stub))
	for _, svc := range p.Real {
		if _, ok := seen[svc]; ok {
			return cperr.Newf(cperr.CategoryConfig,
				"service %q duplicated under real", svc)
		}
		seen[svc] = "real"
	}
	for _, svc := range p.Stub {
		if prior, ok := seen[svc]; ok {
			if prior == "stub" {
				return cperr.Newf(cperr.CategoryConfig,
					"service %q duplicated under stub", svc)
			}
			return cperr.Newf(cperr.CategoryConfig,
				"service %q listed in both real and stub", svc)
		}
		seen[svc] = "stub"
	}

	for _, cap := range p.Requires {
		if !slices.Contains(ValidCapabilities, cap) {
			return cperr.Newf(cperr.CategoryConfig,
				"unknown capability %q (valid: %v)", cap, ValidCapabilities)
		}
	}
	for _, cloud := range p.Clouds {
		if !slices.Contains(ValidClouds, cloud) {
			return cperr.Newf(cperr.CategoryConfig,
				"unknown cloud %q (valid: %v)", cloud, ValidClouds)
		}
	}
	return nil
}
