package v1

import (
	"testing"

	. "github.com/onsi/gomega"
)

func TestAccount_ValidateUpdate(t *testing.T) {
	awsConfig := &AWSConfig{
		AccountID:     "12345",
		AssumeRoleARN: "arn:aws:iam::12345:role/role",
		ExternalID:    nil,
	}
	gcpConfig := &GCPConfig{
		ProjectID:      "12345",
		ServiceAccount: "service-account",
	}

	awsAccount := &Account{
		Spec: AccountSpec{
			Provider: "aws",
			AWS:      awsConfig,
		},
	}
	gcpAccount := &Account{
		Spec: AccountSpec{
			Provider: "gcp",
			GCP:      gcpConfig,
		},
	}

	tests := []struct {
		name       string
		oldAccount *Account
		newAccount *Account
		wantErr    bool
	}{
		{
			name:       "update nothing 1",
			oldAccount: awsAccount,
			newAccount: awsAccount.DeepCopy(),
			wantErr:    false,
		},
		{
			name:       "update nothing 2",
			oldAccount: gcpAccount,
			newAccount: gcpAccount.DeepCopy(),
			wantErr:    false,
		},
		{
			name:       "update provider",
			oldAccount: awsAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "gcp",
					AWS:      awsConfig,
				},
			},
			wantErr: true,
		},
		{
			name: "add AWS config",
			oldAccount: &Account{
				Spec: AccountSpec{
					Provider: "aws",
				},
			},
			newAccount: awsAccount,
			wantErr:    true,
		},
		{
			name:       "update AWS AccountID",
			oldAccount: awsAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "aws",
					AWS: &AWSConfig{
						AccountID:     "54321",
						AssumeRoleARN: "arn:aws:iam::12345:role/role",
						ExternalID:    nil,
					},
				},
			},
			wantErr: true,
		},
		{
			name:       "update AWS AssumeRoleARN",
			oldAccount: awsAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "aws",
					AWS: &AWSConfig{
						AccountID:     "12345",
						AssumeRoleARN: "arn:aws:iam::54321:role/role",
						ExternalID:    nil,
					},
				},
			},
			wantErr: true,
		},
		{
			name:       "update AWS ExternalID",
			oldAccount: awsAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "aws",
					AWS: &AWSConfig{
						AccountID:     "12345",
						AssumeRoleARN: "arn:aws:iam::12345:role/role",
						ExternalID:    &[]string{"12345"}[0],
					},
				},
			},
			wantErr: true,
		},
		{
			name:       "remove AWS config",
			oldAccount: awsAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "aws",
				},
			},
			wantErr: true,
		},
		{
			name: "add GCP config",
			oldAccount: &Account{
				Spec: AccountSpec{
					Provider: "gcp",
				},
			},
			newAccount: gcpAccount,
			wantErr:    true,
		},
		{
			name:       "update GCP ProjectID",
			oldAccount: gcpAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "gcp",
					GCP: &GCPConfig{
						ProjectID:      "54321",
						ServiceAccount: "service-account",
					},
				},
			},
			wantErr: true,
		},
		{
			name:       "update GCP ServiceAccount",
			oldAccount: gcpAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "gcp",
					GCP: &GCPConfig{
						ProjectID:      "12345",
						ServiceAccount: "another-service-account",
					},
				},
			},
			wantErr: true,
		},
		{
			name:       "remove GCP config",
			oldAccount: gcpAccount,
			newAccount: &Account{
				Spec: AccountSpec{
					Provider: "gcp",
				},
			},
			wantErr: true,
		},
	}

	g := NewGomegaWithT(t)
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.wantErr {
				g.Expect(tt.newAccount.ValidateUpdate(tt.oldAccount)).ShouldNot(BeNil())
			} else {
				g.Expect(tt.newAccount.ValidateUpdate(tt.oldAccount)).Should(BeNil())
			}
		})
	}
}
