package mock

import (
	"context"
	"sync"

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

// InstanceRepositoryMock 实例仓储 Mock 实现（内存存储）
type InstanceRepositoryMock struct {
	mu        sync.RWMutex
	instances map[string]*entity.Instance // key: instance ID
}

// NewInstanceRepositoryMock 创建 Mock 实现
func NewInstanceRepositoryMock() repository.InstanceRepository {
	return &InstanceRepositoryMock{
		instances: make(map[string]*entity.Instance),
	}
}

func (r *InstanceRepositoryMock) Create(ctx context.Context, instance *entity.Instance) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	// 检查同一集群中名称是否已存在
	for _, inst := range r.instances {
		if inst.ClusterID == instance.ClusterID && inst.Name == instance.Name {
			return entity.ErrInstanceExists
		}
	}

	r.instances[instance.ID] = instance
	return nil
}

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

	instance, exists := r.instances[id]
	if !exists {
		return nil, entity.ErrInstanceNotFound
	}

	return instance, nil
}

func (r *InstanceRepositoryMock) GetByClusterAndName(ctx context.Context, clusterID, name string) (*entity.Instance, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	for _, instance := range r.instances {
		if instance.ClusterID == clusterID && instance.Name == name {
			return instance, nil
		}
	}

	return nil, entity.ErrInstanceNotFound
}

func (r *InstanceRepositoryMock) Update(ctx context.Context, instance *entity.Instance) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if _, exists := r.instances[instance.ID]; !exists {
		return entity.ErrInstanceNotFound
	}

	r.instances[instance.ID] = instance
	return nil
}

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

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

	delete(r.instances, id)
	return nil
}

func (r *InstanceRepositoryMock) ListByCluster(ctx context.Context, clusterID string) ([]*entity.Instance, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	instances := make([]*entity.Instance, 0)
	for _, instance := range r.instances {
		if instance.ClusterID == clusterID {
			instances = append(instances, instance)
		}
	}

	return instances, nil
}

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

	instances := make([]*entity.Instance, 0, len(r.instances))
	for _, instance := range r.instances {
		instances = append(instances, instance)
	}

	return instances, nil
}
