package aws

import (
	"context"
	"errors"
	"testing"

	"github.com/aws/aws-sdk-go-v2/aws"
	ec2api "github.com/aws/aws-sdk-go-v2/service/ec2"
	"github.com/aws/aws-sdk-go-v2/service/ec2/types"
	. "github.com/onsi/gomega"
	mocks "github.com/tidbcloud/observability/test/mockresourceworker/providers/aws"
	"go.uber.org/mock/gomock"
)

func newMockEndpointService(cfg aws.Config, mock endpointServiceClient) EndpointServiceClient {
	return EndpointServiceClient{
		cli: mock,
		cfg: cfg,
	}
}

func TestEPSCreateEndpointService(t *testing.T) {
	g := NewGomegaWithT(t)
	ctl := gomock.NewController(t)
	defer ctl.Finish()
	var cfg aws.Config
	mockclient := mocks.NewMockendpointServiceClient(ctl)
	epsclient := newMockEndpointService(cfg, mockclient)
	mockclient.EXPECT().CreateVpcEndpointServiceConfiguration(context.TODO(), &ec2api.CreateVpcEndpointServiceConfigurationInput{
		ClientToken:             aws.String("test1"),
		AcceptanceRequired:      aws.Bool(false),
		NetworkLoadBalancerArns: []string{"testarn"},
	}).Return(&ec2api.CreateVpcEndpointServiceConfigurationOutput{
		ClientToken: aws.String("test1"),
		ServiceConfiguration: &types.ServiceConfiguration{
			AcceptanceRequired: aws.Bool(false),
		},
	}, nil)
	g.Expect(epsclient.CreateEndpointService(context.TODO(), "test1", []string{"testarn"})).Should(Equal(&ec2api.CreateVpcEndpointServiceConfigurationOutput{
		ClientToken: aws.String("test1"),
		ServiceConfiguration: &types.ServiceConfiguration{
			AcceptanceRequired: aws.Bool(false),
		}}), nil)
}

func TestEPSModifyUserPermissions(t *testing.T) {
	g := NewGomegaWithT(t)
	ctl := gomock.NewController(t)
	defer ctl.Finish()
	var cfg aws.Config
	mockclient := mocks.NewMockendpointServiceClient(ctl)
	epsclient := newMockEndpointService(cfg, mockclient)
	//add permissions
	mockclient.EXPECT().ModifyVpcEndpointServicePermissions(context.TODO(), &ec2api.ModifyVpcEndpointServicePermissionsInput{
		ServiceId:            aws.String("test1"),
		AddAllowedPrincipals: []string{"testarn"},
	}).Return(&ec2api.ModifyVpcEndpointServicePermissionsOutput{}, nil)
	g.Expect(epsclient.AddUserPermissions(context.TODO(), "test1", []string{"testarn"})).Should(Succeed())
	//delete permissions
	mockclient.EXPECT().ModifyVpcEndpointServicePermissions(context.TODO(), &ec2api.ModifyVpcEndpointServicePermissionsInput{
		ServiceId:               aws.String("test1"),
		RemoveAllowedPrincipals: []string{"testarn"},
	}).Return(&ec2api.ModifyVpcEndpointServicePermissionsOutput{}, nil)
	g.Expect(epsclient.DeleteUserPermissions(context.TODO(), "test1", []string{"testarn"})).Should(Succeed())
}

func TestEPSGetEndpointService(t *testing.T) {
	g := NewGomegaWithT(t)
	ctl := gomock.NewController(t)
	defer ctl.Finish()
	var cfg aws.Config
	mockclient := mocks.NewMockendpointServiceClient(ctl)
	epsclient := newMockEndpointService(cfg, mockclient)
	mockclient.EXPECT().DescribeVpcEndpointServiceConfigurations(context.TODO(), &ec2api.DescribeVpcEndpointServiceConfigurationsInput{
		Filters: []types.Filter{
			{
				Name:   aws.String("service-id"),
				Values: []string{"test1"},
			},
		},
	}).Return(&ec2api.DescribeVpcEndpointServiceConfigurationsOutput{
		ServiceConfigurations: []types.ServiceConfiguration{
			{
				AcceptanceRequired: aws.Bool(false),
				ServiceId:          aws.String("test1"),
			},
		},
	}, nil)
	g.Expect(epsclient.GetEndpointService(context.TODO(), "test1")).Should(Equal(&types.ServiceConfiguration{
		AcceptanceRequired: aws.Bool(false),
		ServiceId:          aws.String("test1"),
	}), nil)
	mockclient.EXPECT().DescribeVpcEndpointServiceConfigurations(context.TODO(), &ec2api.DescribeVpcEndpointServiceConfigurationsInput{
		Filters: []types.Filter{
			{
				Name:   aws.String("service-id"),
				Values: []string{"notfound"},
			},
		},
	}).Return(&ec2api.DescribeVpcEndpointServiceConfigurationsOutput{}, nil)
	g.Expect(epsclient.GetEndpointService(context.TODO(), "notfound")).Error().Should(Equal(errors.New(ErrNotFoundEndpointService)))
	mockclient.EXPECT().DescribeVpcEndpointServiceConfigurations(context.TODO(), &ec2api.DescribeVpcEndpointServiceConfigurationsInput{
		Filters: []types.Filter{
			{
				Name:   aws.String("service-id"),
				Values: []string{"error"},
			},
		},
	}).Return(&ec2api.DescribeVpcEndpointServiceConfigurationsOutput{}, errors.New("someting"))
	g.Expect(epsclient.GetEndpointService(context.TODO(), "error")).Error().Should(HaveOccurred())
}

func TestEPSDeleteEndpointService(t *testing.T) {
	g := NewGomegaWithT(t)
	ctl := gomock.NewController(t)
	defer ctl.Finish()
	var cfg aws.Config
	mockclient := mocks.NewMockendpointServiceClient(ctl)
	epsclient := newMockEndpointService(cfg, mockclient)
	mockclient.EXPECT().DeleteVpcEndpointServiceConfigurations(context.TODO(), &ec2api.DeleteVpcEndpointServiceConfigurationsInput{
		ServiceIds: []string{"test1"},
	}).Return(&ec2api.DeleteVpcEndpointServiceConfigurationsOutput{}, nil)
	g.Expect(epsclient.DeleteEndpointService(context.TODO(), "test1")).Should(Succeed())
}
