package modelaccess

import "strings"

// ScopeAllowsTask reports whether scopes authorize one public task kind.
// Empty scopes retain the legacy unrestricted behavior for old API keys.
func ScopeAllowsTask(scopes []string, kind string) bool {
	if len(scopes) == 0 {
		return true
	}
	return scopeAllowsCapability(scopes, capabilityForTaskKind(kind))
}

// ScopeAllowsModelType reports whether scopes authorize one runtime model type.
// Unknown model types are deny-by-default unless the key has all or an exact
// custom scope matching that model type.
func ScopeAllowsModelType(scopes []string, modelType string) bool {
	if len(scopes) == 0 {
		return true
	}
	modelType = normalize(modelType)
	if modelType == "" {
		return false
	}
	capability := capabilityForModelType(modelType)
	if capability == "" {
		return hasScope(scopes, modelType)
	}
	return scopeAllowsCapability(scopes, capability)
}

// FilterModelTypes keeps the declared order while removing model types that
// the key cannot invoke.
func FilterModelTypes(scopes []string, modelTypes []string) []string {
	if len(modelTypes) == 0 {
		return nil
	}
	filtered := make([]string, 0, len(modelTypes))
	seen := map[string]bool{}
	for _, modelType := range modelTypes {
		normalized := normalize(modelType)
		if normalized == "" || seen[normalized] || !ScopeAllowsModelType(scopes, normalized) {
			continue
		}
		seen[normalized] = true
		filtered = append(filtered, normalized)
	}
	return filtered
}

func capabilityForTaskKind(kind string) string {
	switch normalize(kind) {
	case "chat.completions", "responses":
		return "chat"
	case "embeddings":
		return "embedding"
	case "reranks":
		return "rerank"
	case "images.generations", "images.edits":
		return "image"
	case "images.vectorize":
		return "image_vectorize"
	case "videos.generations":
		return "video"
	case "videos.upscales":
		return "video_enhance"
	case "song.generations", "music.generations":
		return "music"
	case "speech.generations":
		return "audio"
	case "voice.clone":
		return "voice_clone"
	default:
		return normalize(kind)
	}
}

func capabilityForModelType(modelType string) string {
	switch normalize(modelType) {
	case "text_generate", "tools_call":
		return "chat"
	case "text_embedding":
		return "embedding"
	case "text_rerank":
		return "rerank"
	case "image_generate", "image_edit", "image_analysis":
		return "image"
	case "image_vectorize":
		return "image_vectorize"
	case "video_generate", "image_to_video", "text_to_video", "video_edit", "video_reference", "video_first_last_frame", "video_understanding", "omni_video", "omni":
		return "video"
	case "video_enhance":
		return "video_enhance"
	case "audio_generate", "music_generate":
		return "music"
	case "text_to_speech", "audio_understanding":
		return "audio"
	case "voice_clone":
		return "voice_clone"
	default:
		return ""
	}
}

func scopeAllowsCapability(scopes []string, capability string) bool {
	capability = normalize(capability)
	if capability == "" {
		return false
	}
	for _, scope := range scopes {
		scope = normalize(scope)
		if scope == "*" || scope == "all" || scope == capability {
			return true
		}
		switch capability {
		case "chat":
			if scope == "text" || scope == "text_generate" {
				return true
			}
		case "embedding":
			if scope == "text_embedding" {
				return true
			}
		case "rerank":
			if scope == "text_rerank" {
				return true
			}
		case "music":
			if scope == "audio_generate" || scope == "music_generate" || scope == "song" {
				return true
			}
		case "audio":
			if scope == "text_to_speech" || scope == "speech" || scope == "tts" {
				return true
			}
		case "voice_clone":
			if scope == "audio" || scope == "text_to_speech" || scope == "speech" || scope == "tts" {
				return true
			}
		case "image_vectorize":
			if scope == "image" || scope == "vectorize" {
				return true
			}
		case "video_enhance":
			if scope == "video" || scope == "video_upscale" || scope == "upscale" {
				return true
			}
		}
	}
	return false
}

func hasScope(scopes []string, want string) bool {
	want = normalize(want)
	for _, scope := range scopes {
		scope = normalize(scope)
		if scope == "*" || scope == "all" || scope == want {
			return true
		}
	}
	return false
}

func normalize(value string) string {
	return strings.ReplaceAll(strings.ToLower(strings.TrimSpace(value)), "-", "_")
}
