package services

import (
	"context"
	"fmt"

	dpmv1 "github.com/tidbcloud/cluster-service-ng/api/dataplane-manager/v1"
	"github.com/tidbcloud/cluster-service-ng/hack/mock-dpm/store"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
)

// PrivateLinkConnectionService implements the PrivateLinkConnectionServiceServer interface.
type PrivateLinkConnectionService struct {
	dpmv1.UnimplementedPrivateLinkConnectionServiceServer
	store *store.MemoryStore
}

// NewPrivateLinkConnectionService creates a new PrivateLinkConnectionService.
func NewPrivateLinkConnectionService(s *store.MemoryStore) *PrivateLinkConnectionService {
	return &PrivateLinkConnectionService{store: s}
}

// CreatePrivateLinkService creates a new private link service.
func (s *PrivateLinkConnectionService) CreatePrivateLinkService(ctx context.Context, req *dpmv1.CreatePrivateLinkServiceRequest) (*dpmv1.PrivateLinkService, error) {
	if req.DataPlaneId == "" || req.Id == "" {
		return nil, status.Error(codes.InvalidArgument, "data_plane_id and id are required")
	}
	if req.PrivateLinkService == nil {
		return nil, status.Error(codes.InvalidArgument, "private_link_service is required")
	}

	// Check if already exists (idempotent)
	if existing, ok := s.store.GetPrivateLinkService(req.DataPlaneId, req.Id); ok {
		return existing, nil
	}

	plService := &dpmv1.PrivateLinkService{
		Id:               req.Id,
		LoadBalancerName: req.PrivateLinkService.LoadBalancerName,
		ServiceDnsName:   fmt.Sprintf("%s.privatelink.mock.tidbcloud.com", req.Id),
		Tags:             req.PrivateLinkService.Tags,
		Info: &dpmv1.PrivateLinkService_Aws_{
			Aws: &dpmv1.PrivateLinkService_Aws{
				AzIds:       []string{"use1-az1", "use1-az2", "use1-az3"},
				ServiceName: fmt.Sprintf("com.amazonaws.vpce.us-east-1.mock-%s", req.Id),
			},
		},
		Connections: []*dpmv1.PrivateLinkService_Connection{},
		Status:      dpmv1.PrivateLinkService_ACTIVE,
	}

	s.store.SetPrivateLinkService(req.DataPlaneId, plService)
	return plService, nil
}

// GetPrivateLinkService retrieves a private link service by ID.
func (s *PrivateLinkConnectionService) GetPrivateLinkService(ctx context.Context, req *dpmv1.GetPrivateLinkServiceRequest) (*dpmv1.PrivateLinkService, error) {
	if req.DataPlaneId == "" || req.Id == "" {
		return nil, status.Error(codes.InvalidArgument, "data_plane_id and id are required")
	}

	plService, ok := s.store.GetPrivateLinkService(req.DataPlaneId, req.Id)
	if !ok {
		return nil, status.Error(codes.NotFound, "private link service not found")
	}

	return plService, nil
}

// UpdatePrivateLinkService updates a private link service.
func (s *PrivateLinkConnectionService) UpdatePrivateLinkService(ctx context.Context, req *dpmv1.UpdatePrivateLinkServiceRequest) (*dpmv1.PrivateLinkService, error) {
	if req.DataPlaneId == "" || req.Id == "" {
		return nil, status.Error(codes.InvalidArgument, "data_plane_id and id are required")
	}

	existing, ok := s.store.GetPrivateLinkService(req.DataPlaneId, req.Id)
	if !ok {
		return nil, status.Error(codes.NotFound, "private link service not found")
	}

	// Update connections
	existing.Connections = make([]*dpmv1.PrivateLinkService_Connection, 0, len(req.PrivateLinkConnections))
	for _, conn := range req.PrivateLinkConnections {
		existing.Connections = append(existing.Connections, conn)
	}

	s.store.SetPrivateLinkService(req.DataPlaneId, existing)
	return existing, nil
}

// DeletePrivateLinkService deletes a private link service.
func (s *PrivateLinkConnectionService) DeletePrivateLinkService(ctx context.Context, req *dpmv1.DeletePrivateLinkServiceRequest) (*emptypb.Empty, error) {
	if req.DataPlaneId == "" || req.Id == "" {
		return nil, status.Error(codes.InvalidArgument, "data_plane_id and id are required")
	}

	s.store.DeletePrivateLinkService(req.DataPlaneId, req.Id)
	return &emptypb.Empty{}, nil
}

// CreatePrivateLinkEndpoint creates a new private link endpoint.
func (s *PrivateLinkConnectionService) CreatePrivateLinkEndpoint(ctx context.Context, req *dpmv1.CreatePrivateLinkEndpointRequest) (*dpmv1.PrivateLinkEndpoint, error) {
	if req.Id == "" {
		return nil, status.Error(codes.InvalidArgument, "id is required")
	}
	if req.PrivateLinkEndpoint == nil {
		return nil, status.Error(codes.InvalidArgument, "private_link_endpoint is required")
	}

	// Mock implementation
	return &dpmv1.PrivateLinkEndpoint{
		Id:             req.Id,
		Tags:           req.PrivateLinkEndpoint.Tags,
		RootDomainName: req.PrivateLinkEndpoint.RootDomainName,
		Status:         dpmv1.PrivateLinkEndpoint_AVAILABLE,
	}, nil
}

// GetPrivateLinkEndpoint retrieves a private link endpoint by ID.
func (s *PrivateLinkConnectionService) GetPrivateLinkEndpoint(ctx context.Context, req *dpmv1.GetPrivateLinkEndpointRequest) (*dpmv1.PrivateLinkEndpoint, error) {
	return &dpmv1.PrivateLinkEndpoint{
		Id:     req.Id,
		Status: dpmv1.PrivateLinkEndpoint_AVAILABLE,
	}, nil
}

// ListPrivateLinkEndpoints lists all private link endpoints.
func (s *PrivateLinkConnectionService) ListPrivateLinkEndpoints(ctx context.Context, req *dpmv1.ListPrivateLinkEndpointsRequest) (*dpmv1.ListPrivateLinkEndpointsResponse, error) {
	return &dpmv1.ListPrivateLinkEndpointsResponse{
		PrivateLinkEndpoints: []*dpmv1.PrivateLinkEndpoint{},
	}, nil
}

// DeletePrivateLinkEndpoint deletes a private link endpoint.
func (s *PrivateLinkConnectionService) DeletePrivateLinkEndpoint(ctx context.Context, req *dpmv1.DeletePrivateLinkEndpointRequest) (*emptypb.Empty, error) {
	return &emptypb.Empty{}, nil
}

// ValidatePrivateLinkEndpointZones validates private link endpoint zones.
func (s *PrivateLinkConnectionService) ValidatePrivateLinkEndpointZones(ctx context.Context, req *dpmv1.ValidatePrivateLinkEndpointZonesRequest) (*emptypb.Empty, error) {
	return &emptypb.Empty{}, nil
}
