package accountserviceimp

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tech/sendico/pkg/merrors"
	"github.com/tech/sendico/pkg/model"
	"go.mongodb.org/mongo-driver/v2/bson"
)

func TestDeleteAccount_Validation(t *testing.T) {
	t.Run("DeleteAccount_LastMemberFails", func(t *testing.T) {
		orgID := bson.NewObjectID()
		accountID := bson.NewObjectID()

		org := &model.Organization{
			OrganizationBase: model.OrganizationBase{
				Describable: model.Describable{Name: "Single Member Org"},
			},
			Members: []bson.ObjectID{accountID}, // Only one member
		}
		org.ID = orgID

		// This should fail because it's the only member
		err := validateDeleteAccount(org)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "Cannot delete the only member")
	})

	t.Run("DeleteAccount_MultipleMembersSuccess", func(t *testing.T) {
		orgID := bson.NewObjectID()
		accountID := bson.NewObjectID()
		otherAccountID := bson.NewObjectID()

		org := &model.Organization{
			OrganizationBase: model.OrganizationBase{
				Describable: model.Describable{Name: "Multi Member Org"},
			},
			Members: []bson.ObjectID{accountID, otherAccountID}, // Multiple members
		}
		org.ID = orgID

		// This should succeed because there are multiple members
		err := validateDeleteAccount(org)
		require.NoError(t, err)
	})

	t.Run("DeleteAccount_EmptyMembersList", func(t *testing.T) {
		orgID := bson.NewObjectID()

		org := &model.Organization{
			OrganizationBase: model.OrganizationBase{
				Describable: model.Describable{Name: "Empty Org"},
			},
			Members: []bson.ObjectID{}, // No members
		}
		org.ID = orgID

		// This should fail because there are no members
		err := validateDeleteAccount(org)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "Cannot delete the only member")
	})
}

func TestDeleteOrganization_Validation(t *testing.T) {
	t.Run("DeleteOrganization_NilOrganization", func(t *testing.T) {
		err := validateDeleteOrganization(nil)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "organization cannot be nil")
	})

	t.Run("DeleteOrganization_EmptyOrganization", func(t *testing.T) {
		org := &model.Organization{}
		err := validateDeleteOrganization(org)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "organization ID cannot be empty")
	})

	t.Run("DeleteOrganization_ValidOrganization", func(t *testing.T) {
		org := &model.Organization{
			OrganizationBase: model.OrganizationBase{
				Describable: model.Describable{Name: "Valid Organization"},
			},
		}
		org.ID = bson.NewObjectID()

		err := validateDeleteOrganization(org)
		require.NoError(t, err)
	})
}

func TestDeleteAll_Validation(t *testing.T) {
	t.Run("DeleteAll_NilOrganization", func(t *testing.T) {
		accountID := bson.NewObjectID()
		err := validateDeleteAll(nil, accountID)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "organization cannot be nil")
	})

	t.Run("DeleteAll_EmptyAccountID", func(t *testing.T) {
		org := &model.Organization{
			OrganizationBase: model.OrganizationBase{
				Describable: model.Describable{Name: "Valid Organization"},
			},
		}
		org.ID = bson.NewObjectID()

		err := validateDeleteAll(org, bson.NilObjectID)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "account ID cannot be empty")
	})

	t.Run("DeleteAll_ValidInput", func(t *testing.T) {
		org := &model.Organization{
			OrganizationBase: model.OrganizationBase{
				Describable: model.Describable{Name: "Valid Organization"},
			},
		}
		org.ID = bson.NewObjectID()
		accountID := bson.NewObjectID()

		err := validateDeleteAll(org, accountID)
		require.NoError(t, err)
	})
}

// Helper functions that implement the validation logic from the service
func validateDeleteAccount(org *model.Organization) error {
	if len(org.Members) <= 1 {
		return merrors.InvalidArgument("Cannot delete the only member of an organization")
	}
	return nil
}

func validateDeleteOrganization(org *model.Organization) error {
	if org == nil {
		return merrors.InvalidArgument("organization cannot be nil")
	}
	if org.ID == bson.NilObjectID {
		return merrors.InvalidArgument("organization ID cannot be empty")
	}
	return nil
}

func validateDeleteAll(org *model.Organization, accountRef bson.ObjectID) error {
	if org == nil {
		return merrors.InvalidArgument("organization cannot be nil")
	}
	if accountRef == bson.NilObjectID {
		return merrors.InvalidArgument("account ID cannot be empty")
	}
	return nil
}
