package service

import (
	"context"
	"github.com/google/uuid"
	"github.com/ocdp/cluster-service/internal/domain/entity"
	"github.com/ocdp/cluster-service/internal/domain/repository"
	"github.com/ocdp/cluster-service/internal/pkg/authz"
)

// ClusterService 集群管理领域服务
type ClusterService struct {
	clusterRepo repository.ClusterRepository
}

// NewClusterService 创建集群服务
func NewClusterService(clusterRepo repository.ClusterRepository) *ClusterService {
	return &ClusterService{
		clusterRepo: clusterRepo,
	}
}

// CreateCluster 创建新集群
func (s *ClusterService) CreateCluster(ctx context.Context, cluster *entity.Cluster) error {
	principal, err := authz.RequirePrincipal(ctx)
	if err != nil {
		return entity.ErrUnauthorized
	}
	// 生成 ID
	cluster.ID = uuid.New().String()
	cluster.OwnerID = principal.UserID
	cluster.WorkspaceID = principal.WorkspaceID
	if principal.IsAdmin() && cluster.WorkspaceID == "" {
		cluster.WorkspaceID = entity.DefaultWorkspaceID
	}
	if !principal.IsAdmin() && cluster.Visibility == authz.VisibilityGlobalShared {
		return entity.ErrForbidden
	}
	cluster.Visibility = authz.NormalizeVisibility(principal.Role, cluster.Visibility)

	// 验证
	if err := cluster.Validate(); err != nil {
		return err
	}

	// 检查是否已存在
	clusters, _ := s.clusterRepo.List(ctx)
	for _, existingCluster := range clusters {
		if existingCluster.Name == cluster.Name && existingCluster.WorkspaceID == cluster.WorkspaceID && existingCluster.OwnerID == cluster.OwnerID {
			return entity.ErrClusterExists
		}
	}

	return s.clusterRepo.Create(ctx, cluster)
}

// GetCluster 获取集群
func (s *ClusterService) GetCluster(ctx context.Context, id string) (*entity.Cluster, error) {
	principal, err := authz.RequirePrincipal(ctx)
	if err != nil {
		return nil, entity.ErrUnauthorized
	}
	cluster, err := s.clusterRepo.GetByID(ctx, id)
	if err != nil {
		return nil, err
	}
	if !authz.CanReadResource(principal, cluster.WorkspaceID, cluster.OwnerID, cluster.Visibility) {
		return nil, entity.ErrClusterNotFound
	}
	return cluster, nil
}

// UpdateCluster 更新集群
func (s *ClusterService) UpdateCluster(ctx context.Context, cluster *entity.Cluster) error {
	principal, err := authz.RequirePrincipal(ctx)
	if err != nil {
		return entity.ErrUnauthorized
	}
	// 检查是否存在
	existing, err := s.clusterRepo.GetByID(ctx, cluster.ID)
	if err != nil {
		return entity.ErrClusterNotFound
	}
	if !authz.CanWriteResource(principal, existing.WorkspaceID, existing.OwnerID, existing.Visibility) {
		return entity.ErrForbidden
	}
	cluster.WorkspaceID = existing.WorkspaceID
	cluster.OwnerID = existing.OwnerID
	if principal.IsAdmin() {
		cluster.Visibility = authz.NormalizeVisibility(principal.Role, cluster.Visibility)
	} else {
		cluster.Visibility = existing.Visibility
	}

	// 验证
	if err := cluster.Validate(); err != nil {
		return err
	}

	return s.clusterRepo.Update(ctx, cluster)
}

// DeleteCluster 删除集群
func (s *ClusterService) DeleteCluster(ctx context.Context, id string) error {
	principal, err := authz.RequirePrincipal(ctx)
	if err != nil {
		return entity.ErrUnauthorized
	}
	// 检查是否存在
	cluster, err := s.clusterRepo.GetByID(ctx, id)
	if err != nil {
		return entity.ErrClusterNotFound
	}
	if !authz.CanWriteResource(principal, cluster.WorkspaceID, cluster.OwnerID, cluster.Visibility) {
		return entity.ErrForbidden
	}

	return s.clusterRepo.Delete(ctx, id)
}

// ListClusters 列出所有集群
func (s *ClusterService) ListClusters(ctx context.Context) ([]*entity.Cluster, error) {
	principal, err := authz.RequirePrincipal(ctx)
	if err != nil {
		return nil, entity.ErrUnauthorized
	}
	clusters, err := s.clusterRepo.List(ctx)
	if err != nil {
		return nil, err
	}
	visible := make([]*entity.Cluster, 0, len(clusters))
	for _, cluster := range clusters {
		if authz.CanReadResource(principal, cluster.WorkspaceID, cluster.OwnerID, cluster.Visibility) {
			visible = append(visible, cluster)
		}
	}
	return visible, nil
}
