package common

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/privatelinkservice/task"
)

type fakeEndpointProvider struct {
	conns       []task.VpcEndpointConnection
	deleteList  []task.VpcEndpointConnection
	getErr      error
	acceptErr   error
	rejectErr   error
	deleteErr   error
	forceDelete bool
}

func (f *fakeEndpointProvider) GetAllVPCEndpointConns(context.Context) ([]task.VpcEndpointConnection, error) {
	return f.conns, f.getErr
}

func (f *fakeEndpointProvider) AcceptVPCEndpoints(context.Context, []task.VpcEndpointConnection) error {
	return f.acceptErr
}

func (f *fakeEndpointProvider) RejectVPCEndpoints(_ context.Context, _ []task.VpcEndpointConnection) error {
	return f.rejectErr
}

func (f *fakeEndpointProvider) ShouldForceDeleteVPCEndpoints() bool {
	return f.forceDelete
}

func (f *fakeEndpointProvider) DeleteVPCEndpoints(_ context.Context, deleteList []task.VpcEndpointConnection) error {
	f.deleteList = append([]task.VpcEndpointConnection{}, deleteList...)
	return f.deleteErr
}

func TestEndpointDeleteUsesForceDeleteForAzureProvider(t *testing.T) {
	provider := &fakeEndpointProvider{
		conns: []task.VpcEndpointConnection{
			{ConnectionID: "conn-1", Phase: v1alpha1.ConnectionPhaseActive},
			{ConnectionID: "conn-2", Phase: v1alpha1.ConnectionPhaseFailed},
		},
		forceDelete: true,
	}
	endpoint := &Endpoint{
		BaseTask: &task.BaseTask{Context: &task.Context{
			PrivateLinkService: &v1alpha1.PrivateLinkService{},
		}},
		endpointProvider: provider,
	}

	result := endpoint.Delete(context.Background())
	assert.True(t, result.IsDoneState())
	assert.Equal(t, []task.VpcEndpointConnection{
		{ConnectionID: "conn-1", Phase: v1alpha1.ConnectionPhaseActive},
		{ConnectionID: "conn-2", Phase: v1alpha1.ConnectionPhaseFailed},
	}, provider.deleteList)
}

func TestEndpointPostDeleteWaitsForForceDeleteConnections(t *testing.T) {
	endpoint := &Endpoint{
		BaseTask: &task.BaseTask{Context: &task.Context{
			PrivateLinkService: &v1alpha1.PrivateLinkService{},
		}},
		endpointProvider: &fakeEndpointProvider{
			conns:       []task.VpcEndpointConnection{{ConnectionID: "conn-1"}},
			forceDelete: true,
		},
	}

	result := endpoint.PostDelete(context.Background())
	assert.ErrorContains(t, result.Error(), "vpc endpoint connections still exist")
}

func TestEndpointPostDeleteDoneAfterForceDeleteConnectionsRemoved(t *testing.T) {
	endpoint := &Endpoint{
		BaseTask: &task.BaseTask{Context: &task.Context{
			PrivateLinkService: &v1alpha1.PrivateLinkService{},
		}},
		endpointProvider: &fakeEndpointProvider{
			forceDelete: true,
		},
	}

	result := endpoint.PostDelete(context.Background())
	assert.True(t, result.IsDoneState())
}
