package vpcpeering

import (
	"context"
	"testing"

	sdkerrors "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/vpcpeer"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/consts"
)

type fakeAliyunVpcPeerAPI struct {
	listResponse *vpcpeer.ListVpcPeerConnectionsResponse
	getResponse  *vpcpeer.GetVpcPeerConnectionAttributeResponse
	getErr       error
}

func (f *fakeAliyunVpcPeerAPI) ListVpcPeerConnections(*vpcpeer.ListVpcPeerConnectionsRequest) (*vpcpeer.ListVpcPeerConnectionsResponse, error) {
	return f.listResponse, nil
}

func (f *fakeAliyunVpcPeerAPI) GetVpcPeerConnectionAttribute(*vpcpeer.GetVpcPeerConnectionAttributeRequest) (*vpcpeer.GetVpcPeerConnectionAttributeResponse, error) {
	if f.getErr != nil {
		return nil, f.getErr
	}
	return f.getResponse, nil
}

func TestAliyunExternalPeeringQueryer_ListByVPC_NormalizesBothDirections(t *testing.T) {
	q := &aliyunExternalPeeringQueryer{
		peerFactory: func(VPCContext) (aliyunVpcPeerAPI, error) {
			return &fakeAliyunVpcPeerAPI{
				listResponse: &vpcpeer.ListVpcPeerConnectionsResponse{
					VpcPeerConnects: []vpcpeer.VpcPeerConnectsItem{
						{
							InstanceId:        "pc-ali-1",
							Status:            "Activated",
							OwnerId:           123456789012,
							AcceptingOwnerUid: 210987654321,
							RegionId:          "cn-hangzhou",
							AcceptingRegionId: "cn-shanghai",
							Vpc: vpcpeer.Vpc{
								VpcId:     "vpc-12345",
								Ipv4Cidrs: []string{"10.0.0.0/16"},
							},
							AcceptingVpc: vpcpeer.AcceptingVpc{
								VpcId:     "vpc-dst-1",
								Ipv4Cidrs: []string{"10.1.0.0/16"},
							},
						},
						{
							InstanceId:        "pc-ali-2",
							Status:            "Activated",
							OwnerId:           210987654321,
							AcceptingOwnerUid: 123456789012,
							RegionId:          "cn-shanghai",
							AcceptingRegionId: "cn-hangzhou",
							Vpc: vpcpeer.Vpc{
								VpcId:     "vpc-src-2",
								Ipv4Cidrs: []string{"10.2.0.0/16"},
							},
							AcceptingVpc: vpcpeer.AcceptingVpc{
								VpcId:     "vpc-12345",
								Ipv4Cidrs: []string{"10.0.0.0/16"},
							},
						},
					},
				},
			}, nil
		},
	}

	got, err := q.ListByVPC(context.Background(), VPCContext{
		Provider:    consts.ProviderTypeACK,
		Region:      "cn-hangzhou",
		VPCID:       "vpc-12345",
		VPCCIDR:     "10.0.0.0/16",
		AccountID:   "123456789012",
		AccountRole: "regional-server-role",
	})
	require.NoError(t, err)
	require.Len(t, got, 2)
	assert.Equal(t, "pc-ali-1", got[0].ConnectionID)
	assert.Equal(t, "vpc-dst-1", got[0].DestinationSide.VpcID)
	assert.Equal(t, "123456789012", got[0].CurrentSide.AccountID)
	assert.Equal(t, "vpc-src-2", got[1].DestinationSide.VpcID)
}

func TestAliyunExternalPeeringQueryer_ListByVPC_FiltersDeletedPeerings(t *testing.T) {
	q := &aliyunExternalPeeringQueryer{
		peerFactory: func(VPCContext) (aliyunVpcPeerAPI, error) {
			return &fakeAliyunVpcPeerAPI{
				listResponse: &vpcpeer.ListVpcPeerConnectionsResponse{
					VpcPeerConnects: []vpcpeer.VpcPeerConnectsItem{
						{
							InstanceId: "pc-ali-active",
							Status:     "Activated",
							Vpc: vpcpeer.Vpc{
								VpcId: "vpc-12345",
							},
							AcceptingVpc: vpcpeer.AcceptingVpc{
								VpcId: "vpc-dst-1",
							},
						},
						{
							InstanceId: "pc-ali-deleted",
							Status:     "Deleted",
							Vpc: vpcpeer.Vpc{
								VpcId: "vpc-12345",
							},
							AcceptingVpc: vpcpeer.AcceptingVpc{
								VpcId: "vpc-dst-2",
							},
						},
					},
				},
			}, nil
		},
	}

	got, err := q.ListByVPC(context.Background(), VPCContext{Provider: consts.ProviderTypeACK, VPCID: "vpc-12345"})
	require.NoError(t, err)
	require.Len(t, got, 1)
	assert.Equal(t, "pc-ali-active", got[0].ConnectionID)
}

func TestAliyunExternalPeeringQueryer_GetByConnectionID(t *testing.T) {
	q := &aliyunExternalPeeringQueryer{
		peerFactory: func(VPCContext) (aliyunVpcPeerAPI, error) {
			return &fakeAliyunVpcPeerAPI{
				getResponse: &vpcpeer.GetVpcPeerConnectionAttributeResponse{
					InstanceId:        "pc-ali-1",
					Status:            "Creating",
					OwnerId:           123456789012,
					AcceptingOwnerUid: 210987654321,
					RegionId:          "cn-hangzhou",
					AcceptingRegionId: "cn-shanghai",
					Vpc: vpcpeer.Vpc{
						VpcId:     "vpc-12345",
						Ipv4Cidrs: []string{"10.0.0.0/16"},
					},
					AcceptingVpc: vpcpeer.AcceptingVpc{
						VpcId:     "vpc-dst-1",
						Ipv4Cidrs: []string{"10.1.0.0/16"},
					},
				},
			}, nil
		},
	}

	got, err := q.GetByConnectionID(context.Background(), VPCContext{VPCID: "vpc-12345"}, "pc-ali-1")
	require.NoError(t, err)
	require.NotNil(t, got)
	assert.Equal(t, "pc-ali-1", got.ConnectionID)
	assert.Equal(t, "creating", got.Status)
	assert.Equal(t, "vpc-dst-1", got.DestinationSide.VpcID)
}

func TestAliyunExternalPeeringQueryer_GetByConnectionID_DeletedReturnsNil(t *testing.T) {
	q := &aliyunExternalPeeringQueryer{
		peerFactory: func(VPCContext) (aliyunVpcPeerAPI, error) {
			return &fakeAliyunVpcPeerAPI{
				getResponse: &vpcpeer.GetVpcPeerConnectionAttributeResponse{
					InstanceId: "pc-ali-deleted",
					Status:     "Deleted",
					Vpc: vpcpeer.Vpc{
						VpcId: "vpc-12345",
					},
					AcceptingVpc: vpcpeer.AcceptingVpc{
						VpcId: "vpc-dst-1",
					},
				},
			}, nil
		},
	}

	got, err := q.GetByConnectionID(context.Background(), VPCContext{VPCID: "vpc-12345"}, "pc-ali-deleted")
	require.NoError(t, err)
	assert.Nil(t, got)
}

func TestAliyunExternalPeeringQueryer_GetByConnectionID_NotFound(t *testing.T) {
	q := &aliyunExternalPeeringQueryer{
		peerFactory: func(VPCContext) (aliyunVpcPeerAPI, error) {
			return &fakeAliyunVpcPeerAPI{
				getErr: sdkerrors.NewServerError(400, `{"Code":"ResourceNotFound.InstanceId","Message":"not found"}`, ""),
			}, nil
		},
	}

	got, err := q.GetByConnectionID(context.Background(), VPCContext{VPCID: "vpc-12345"}, "pc-ali-missing")
	require.NoError(t, err)
	assert.Nil(t, got)
}
