package mock

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/ocdp/cluster-service/internal/domain/entity"
	"github.com/ocdp/cluster-service/internal/domain/repository"
)

// OCIClientMock OCI Registry 客户端 Mock 实现
type OCIClientMock struct {
	// Mock 数据存储
	repositories map[string][]string                      // registryID -> []repositoryName
	artifacts    map[string]map[string][]*entity.Artifact // registryID -> repository -> []artifact
}

// NewOCIClientMock 创建 Mock 实现
func NewOCIClientMock() repository.OCIClient {
	mock := &OCIClientMock{
		repositories: make(map[string][]string),
		artifacts:    make(map[string]map[string][]*entity.Artifact),
	}

	// 初始化一些测试数据
	mock.initMockData()

	return mock
}

func (c *OCIClientMock) initMockData() {
	// Note: This method intentionally left empty
	// Mock data will be generated dynamically per registry to support any registry ID
}

// initArtifactsForRegistry initializes mock artifacts for a given registry ID
func (c *OCIClientMock) initArtifactsForRegistry(registryID string) {
	c.artifacts[registryID] = make(map[string][]*entity.Artifact)

	// vllm-serve artifacts (OCI 格式的 Helm Chart)
	c.artifacts[registryID]["charts/vllm-serve"] = []*entity.Artifact{
		{
			RegistryID: registryID,
			Repository: "charts/vllm-serve",
			Tag:        "0.1.0",
			Digest:     "sha256:abc123def456",
			Type:       entity.ArtifactTypeChart,
			Size:       12345678,
			MediaType:  "application/vnd.oci.image.manifest.v1+json",
			ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
			Annotations: map[string]string{
				"org.opencontainers.image.title":   "vllm-serve",
				"org.opencontainers.image.version": "0.1.0",
			},
			CreatedAt: time.Now().Add(-24 * time.Hour),
		},
		{
			RegistryID: registryID,
			Repository: "charts/vllm-serve",
			Tag:        "0.2.0",
			Digest:     "sha256:xyz789uvw012",
			Type:       entity.ArtifactTypeChart,
			Size:       13456789,
			MediaType:  "application/vnd.oci.image.manifest.v1+json",
			ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
			Annotations: map[string]string{
				"org.opencontainers.image.title":   "vllm-serve",
				"org.opencontainers.image.version": "0.2.0",
			},
			CreatedAt: time.Now(),
		},
	}

	// nginx artifacts (OCI 格式的 Helm Chart)
	c.artifacts[registryID]["charts/nginx"] = []*entity.Artifact{
		{
			RegistryID: registryID,
			Repository: "charts/nginx",
			Tag:        "1.0.0",
			Digest:     "sha256:nginx123456",
			Type:       entity.ArtifactTypeChart,
			Size:       5678901,
			MediaType:  "application/vnd.oci.image.manifest.v1+json",
			ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
			Annotations: map[string]string{
				"org.opencontainers.image.title": "nginx",
			},
			CreatedAt: time.Now().Add(-48 * time.Hour),
		},
	}

	// redis artifacts (OCI 格式的 Helm Chart)
	c.artifacts[registryID]["charts/redis"] = []*entity.Artifact{
		{
			RegistryID: registryID,
			Repository: "charts/redis",
			Tag:        "6.2.0",
			Digest:     "sha256:redis789abc",
			Type:       entity.ArtifactTypeChart,
			Size:       8901234,
			MediaType:  "application/vnd.oci.image.manifest.v1+json",
			ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
			Annotations: map[string]string{
				"org.opencontainers.image.title":   "redis",
				"org.opencontainers.image.version": "6.2.0",
			},
			CreatedAt: time.Now().Add(-72 * time.Hour),
		},
	}

	// alpine artifacts (Docker Image)
	c.artifacts[registryID]["library/alpine"] = []*entity.Artifact{
		{
			RegistryID: registryID,
			Repository: "library/alpine",
			Tag:        "3.18",
			Digest:     "sha256:alpine123",
			Type:       entity.ArtifactTypeImage,
			Size:       2345678,
			MediaType:  "application/vnd.docker.distribution.manifest.v2+json",
			ConfigType: "application/vnd.docker.container.image.v1+json", // Docker Image 的 config type
			Annotations: map[string]string{
				"org.opencontainers.image.title":   "alpine",
				"org.opencontainers.image.version": "3.18",
			},
			CreatedAt: time.Now().Add(-96 * time.Hour),
		},
		{
			RegistryID: registryID,
			Repository: "library/alpine",
			Tag:        "latest",
			Digest:     "sha256:alpine456",
			Type:       entity.ArtifactTypeImage,
			Size:       2456789,
			MediaType:  "application/vnd.docker.distribution.manifest.v2+json",
			ConfigType: "application/vnd.docker.container.image.v1+json", // Docker Image 的 config type
			Annotations: map[string]string{
				"org.opencontainers.image.title": "alpine",
			},
			CreatedAt: time.Now().Add(-24 * time.Hour),
		},
	}
}

func (c *OCIClientMock) ListRepositories(ctx context.Context, registry *entity.Registry, artifactType string) ([]string, error) {
	// Check if we have cached data for this registry
	repos, exists := c.repositories[registry.ID]
	if !exists {
		// Generate mock data dynamically for any registry
		repos = []string{
			"charts/vllm-serve",
			"charts/nginx",
			"charts/redis",
			"library/alpine",
		}
		c.repositories[registry.ID] = repos

		// Also initialize artifacts for this registry
		c.initArtifactsForRegistry(registry.ID)
	}
	if strings.EqualFold(strings.TrimSpace(artifactType), "chart") {
		chartRepos := make([]string, 0)
		for _, repo := range repos {
			artifacts, _ := c.ListArtifacts(ctx, registry, repo, "chart")
			if len(artifacts) > 0 {
				chartRepos = append(chartRepos, repo)
			}
		}
		return chartRepos, nil
	}
	return repos, nil
}

func (c *OCIClientMock) ListArtifacts(ctx context.Context, registry *entity.Registry, repository, mediaTypeFilter string) ([]*entity.Artifact, error) {
	regArtifacts, exists := c.artifacts[registry.ID]
	if !exists {
		// Initialize artifacts for this registry if not exists
		c.initArtifactsForRegistry(registry.ID)
		regArtifacts = c.artifacts[registry.ID]
	}

	artifacts, exists := regArtifacts[repository]
	if !exists {
		return []*entity.Artifact{}, nil
	}

	// 应用 mediaType 过滤
	if mediaTypeFilter == "" || mediaTypeFilter == "all" {
		return artifacts, nil
	}

	filtered := make([]*entity.Artifact, 0)
	filter := strings.ToLower(strings.TrimSpace(mediaTypeFilter))

	for _, artifact := range artifacts {
		switch filter {
		case "chart":
			if artifact.Type == entity.ArtifactTypeChart {
				filtered = append(filtered, artifact)
			}
		case "image":
			if artifact.Type == entity.ArtifactTypeImage {
				filtered = append(filtered, artifact)
			}
		case "other":
			if artifact.Type == entity.ArtifactTypeOther {
				filtered = append(filtered, artifact)
			}
		}
	}

	return filtered, nil
}

func (c *OCIClientMock) GetArtifact(ctx context.Context, registry *entity.Registry, repository, reference string) (*entity.Artifact, error) {
	regArtifacts, exists := c.artifacts[registry.ID]
	if !exists {
		// Initialize artifacts for this registry if not exists
		c.initArtifactsForRegistry(registry.ID)
		regArtifacts = c.artifacts[registry.ID]
	}

	artifacts, exists := regArtifacts[repository]
	if !exists {
		return nil, entity.ErrArtifactNotFound
	}

	// 根据 tag 或 digest 查找
	for _, artifact := range artifacts {
		if artifact.Tag == reference || artifact.Digest == reference {
			return artifact, nil
		}
	}

	return nil, entity.ErrArtifactNotFound
}

func (c *OCIClientMock) GetValuesSchema(ctx context.Context, registry *entity.Registry, repository, reference string) (string, error) {
	artifact, err := c.GetArtifact(ctx, registry, repository, reference)
	if err != nil {
		return "", err
	}

	if !artifact.IsChart() {
		return "", fmt.Errorf("not a helm chart")
	}

	// 返回 Mock values schema
	mockSchema := `{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "replicaCount": {
      "type": "integer",
      "default": 1
    },
    "image": {
      "type": "object",
      "properties": {
        "repository": {
          "type": "string"
        },
        "tag": {
          "type": "string"
        }
      }
    }
  }
}`
	return mockSchema, nil
}

func (c *OCIClientMock) GetValuesYAML(ctx context.Context, registry *entity.Registry, repository, reference string) (string, error) {
	artifact, err := c.GetArtifact(ctx, registry, repository, reference)
	if err != nil {
		return "", err
	}
	if !artifact.IsChart() {
		return "", fmt.Errorf("not a helm chart")
	}
	return "replicaCount: 1\nimage:\n  repository: nginx\n  tag: latest\nservice:\n  type: ClusterIP\n", nil
}

func (c *OCIClientMock) PullArtifact(ctx context.Context, registry *entity.Registry, repository, reference, destPath string) error {
	_, err := c.GetArtifact(ctx, registry, repository, reference)
	if err != nil {
		return err
	}

	// Mock 实现，不实际下载
	return nil
}

func (c *OCIClientMock) PushArtifact(ctx context.Context, registry *entity.Registry, repository, tag, sourcePath string) error {
	// Mock 实现，不实际上传
	return nil
}

func (c *OCIClientMock) CheckHealth(ctx context.Context, registry *entity.Registry) error {
	// Mock 实现，总是返回健康
	return nil
}
