package mock

import (
	"context"
	"sync"

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

// ClusterRepositoryMock 集群仓储 Mock 实现（内存存储，支持加密）
type ClusterRepositoryMock struct {
	mu        sync.RWMutex
	clusters  map[string]*entity.Cluster // key: cluster ID
	encryptor crypto.Encryptor           // 加密器
}

// NewClusterRepositoryMock 创建 Mock 实现
func NewClusterRepositoryMock(encryptor crypto.Encryptor) repository.ClusterRepository {
	return &ClusterRepositoryMock{
		clusters:  make(map[string]*entity.Cluster),
		encryptor: encryptor,
	}
}

func (r *ClusterRepositoryMock) Create(ctx context.Context, cluster *entity.Cluster) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	// 检查名称是否已存在
	for _, c := range r.clusters {
		if c.Name == cluster.Name {
			return entity.ErrClusterExists
		}
	}

	// Mock 模式：如果没有提供认证信息，自动填充默认的 Mock 证书
	if (cluster.CertData == "" || cluster.KeyData == "") && cluster.Token == "" {
		cluster.CAData = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1vY2sgQ0EgQ2VydGlmaWNhdGUKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ=="
		cluster.CertData = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1vY2sgQ2xpZW50IENlcnRpZmljYXRlCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0="
		cluster.KeyData = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNb2NrIFByaXZhdGUgS2V5Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0t"
	}

	// 加密敏感数据后存储
	encryptedCluster := r.encryptCluster(cluster)
	r.clusters[cluster.ID] = encryptedCluster
	return nil
}

func (r *ClusterRepositoryMock) GetByID(ctx context.Context, id string) (*entity.Cluster, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	cluster, exists := r.clusters[id]
	if !exists {
		return nil, entity.ErrClusterNotFound
	}

	// 解密敏感数据后返回
	return r.decryptCluster(cluster), nil
}

func (r *ClusterRepositoryMock) GetByName(ctx context.Context, name string) (*entity.Cluster, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	for _, cluster := range r.clusters {
		if cluster.Name == name {
			// 解密敏感数据后返回
			return r.decryptCluster(cluster), nil
		}
	}

	return nil, entity.ErrClusterNotFound
}

func (r *ClusterRepositoryMock) Update(ctx context.Context, cluster *entity.Cluster) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if _, exists := r.clusters[cluster.ID]; !exists {
		return entity.ErrClusterNotFound
	}

	// 加密敏感数据后存储
	encryptedCluster := r.encryptCluster(cluster)
	r.clusters[cluster.ID] = encryptedCluster
	return nil
}

func (r *ClusterRepositoryMock) Delete(ctx context.Context, id string) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if _, exists := r.clusters[id]; !exists {
		return entity.ErrClusterNotFound
	}

	delete(r.clusters, id)
	return nil
}

func (r *ClusterRepositoryMock) List(ctx context.Context) ([]*entity.Cluster, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	clusters := make([]*entity.Cluster, 0, len(r.clusters))
	for _, cluster := range r.clusters {
		// 解密敏感数据后返回
		clusters = append(clusters, r.decryptCluster(cluster))
	}

	return clusters, nil
}

// encryptCluster 加密 Cluster 的敏感数据
func (r *ClusterRepositoryMock) encryptCluster(cluster *entity.Cluster) *entity.Cluster {
	encrypted := *cluster // 复制

	// 加密证书数据
	if cluster.CAData != "" && !crypto.IsEncrypted(cluster.CAData) {
		if encryptedData, err := r.encryptor.Encrypt(cluster.CAData); err == nil {
			encrypted.CAData = encryptedData
		}
	}
	if cluster.CertData != "" && !crypto.IsEncrypted(cluster.CertData) {
		if encryptedData, err := r.encryptor.Encrypt(cluster.CertData); err == nil {
			encrypted.CertData = encryptedData
		}
	}
	if cluster.KeyData != "" && !crypto.IsEncrypted(cluster.KeyData) {
		if encryptedData, err := r.encryptor.Encrypt(cluster.KeyData); err == nil {
			encrypted.KeyData = encryptedData
		}
	}
	if cluster.Token != "" && !crypto.IsEncrypted(cluster.Token) {
		if encryptedData, err := r.encryptor.Encrypt(cluster.Token); err == nil {
			encrypted.Token = encryptedData
		}
	}

	return &encrypted
}

// decryptCluster 解密 Cluster 的敏感数据
func (r *ClusterRepositoryMock) decryptCluster(cluster *entity.Cluster) *entity.Cluster {
	decrypted := *cluster // 复制

	// 解密证书数据
	if cluster.CAData != "" && crypto.IsEncrypted(cluster.CAData) {
		if decryptedData, err := r.encryptor.Decrypt(cluster.CAData); err == nil {
			decrypted.CAData = decryptedData
		}
	}
	if cluster.CertData != "" && crypto.IsEncrypted(cluster.CertData) {
		if decryptedData, err := r.encryptor.Decrypt(cluster.CertData); err == nil {
			decrypted.CertData = decryptedData
		}
	}
	if cluster.KeyData != "" && crypto.IsEncrypted(cluster.KeyData) {
		if decryptedData, err := r.encryptor.Decrypt(cluster.KeyData); err == nil {
			decrypted.KeyData = decryptedData
		}
	}
	if cluster.Token != "" && crypto.IsEncrypted(cluster.Token) {
		if decryptedData, err := r.encryptor.Decrypt(cluster.Token); err == nil {
			decrypted.Token = decryptedData
		}
	}

	return &decrypted
}
