package entity

import (
	"strings"
	"time"
)

// ArtifactType Artifact 类型
type ArtifactType string

const (
	ArtifactTypeChart ArtifactType = "chart" // Helm Chart
	ArtifactTypeImage ArtifactType = "image" // Docker/OCI Image
	ArtifactTypeOther ArtifactType = "other" // Other types
)

// Artifact OCI Artifact 领域实体
type Artifact struct {
	RegistryID  string
	Repository  string
	Tag         string
	Digest      string
	Type        ArtifactType
	Size        int64
	MediaType   string
	ConfigType  string // Config layer 的 mediaType (用于更准确的类型判断)
	Annotations map[string]string
	CreatedAt   time.Time
}

// Repository 仓库信息
type Repository struct {
	RegistryID string
	Name       string
	TagCount   int
}

// NewArtifact 创建新 Artifact
func NewArtifact(registryID, repository, tag, digest string) *Artifact {
	return &Artifact{
		RegistryID:  registryID,
		Repository:  repository,
		Tag:         tag,
		Digest:      digest,
		Annotations: make(map[string]string),
		CreatedAt:   time.Now(),
	}
}

// SetType 设置 Artifact 类型（根据 mediaType 识别为 chart | image | other）
// 已废弃：请使用 DetermineType() 方法，它提供更准确的类型判断
func (a *Artifact) SetType(mediaType string) {
	lowerMediaType := strings.ToLower(strings.TrimSpace(mediaType))

	containsAny := func(target string, keywords ...string) bool {
		for _, keyword := range keywords {
			if keyword != "" && strings.Contains(target, keyword) {
				return true
			}
		}
		return false
	}

	switch {
	case lowerMediaType == "":
		a.Type = ArtifactTypeOther
	case containsAny(lowerMediaType,
		"helm", "cncf.helm", "helm.chart", "helm+", "chart+json", "chart.v1", "helm-package", "helm.config",
	):
		a.Type = ArtifactTypeChart
	case containsAny(lowerMediaType,
		"docker", "vnd.docker", "docker.distribution", "docker.container.image",
		"vnd.oci", "oci.image", "opencontainers", "container.image",
	):
		a.Type = ArtifactTypeImage
	case strings.Contains(lowerMediaType, "image") || strings.Contains(lowerMediaType, "manifest") || strings.Contains(lowerMediaType, "container"):
		a.Type = ArtifactTypeImage
	default:
		a.Type = ArtifactTypeOther
	}
}

// DetermineType 智能判断 Artifact 类型（综合多种信息）
// 优先级：
// 1. ConfigType (config.mediaType) - 最准确
// 2. Annotations - 可能包含类型标注
// 3. Repository 名称 - charts/ 前缀暗示
// 4. MediaType - 兜底判断
func (a *Artifact) DetermineType() {
	containsAny := func(target string, keywords ...string) bool {
		for _, keyword := range keywords {
			if keyword != "" && strings.Contains(target, keyword) {
				return true
			}
		}
		return false
	}

	// 1. 优先检查 ConfigType（最准确的判断方式）
	if a.ConfigType != "" {
		lowerConfigType := strings.ToLower(strings.TrimSpace(a.ConfigType))

		// Helm Chart 的 config.mediaType
		if containsAny(lowerConfigType,
			"helm.config", "cncf.helm", "helm.chart", "chart.content",
		) {
			a.Type = ArtifactTypeChart
			return
		}

		// Docker/OCI Image 的 config.mediaType
		if containsAny(lowerConfigType,
			"docker.container.image", "oci.image.config",
		) {
			a.Type = ArtifactTypeImage
			return
		}
	}

	// 2. 检查 Annotations
	for key, value := range a.Annotations {
		lowerKey := strings.ToLower(key)
		lowerValue := strings.ToLower(value)

		if containsAny(lowerKey, "helm", "chart") ||
			containsAny(lowerValue, "helm", "chart") {
			a.Type = ArtifactTypeChart
			return
		}
	}

	// 3. 检查 Repository 名称（辅助判断）
	if strings.HasPrefix(strings.ToLower(a.Repository), "charts/") {
		// charts/ 开头的仓库很可能是 Helm Chart
		// 但需要结合 MediaType 进一步确认
		lowerMediaType := strings.ToLower(strings.TrimSpace(a.MediaType))

		// 如果是 OCI manifest 格式，很可能是以 OCI 格式存储的 Helm Chart
		if strings.Contains(lowerMediaType, "oci.image.manifest") ||
			strings.Contains(lowerMediaType, "vnd.oci") {
			a.Type = ArtifactTypeChart
			return
		}
	}

	// 4. 回退到基于 MediaType 的判断（兜底逻辑）
	lowerMediaType := strings.ToLower(strings.TrimSpace(a.MediaType))

	switch {
	case lowerMediaType == "":
		a.Type = ArtifactTypeOther
	case containsAny(lowerMediaType,
		"helm", "cncf.helm", "helm.chart", "helm+", "chart+json", "chart.v1", "helm-package", "helm.config",
	):
		a.Type = ArtifactTypeChart
	case containsAny(lowerMediaType,
		"docker", "vnd.docker", "docker.distribution", "docker.container.image",
	):
		a.Type = ArtifactTypeImage
	case strings.Contains(lowerMediaType, "image") || strings.Contains(lowerMediaType, "manifest"):
		a.Type = ArtifactTypeImage
	default:
		a.Type = ArtifactTypeOther
	}
}

// IsChart 判断是否为 Helm Chart
func (a *Artifact) IsChart() bool {
	return a.Type == ArtifactTypeChart
}
