package domain_test

import (
	"testing"
	"time"

	"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
	"gitea.dwysokinski.me/twhelp/corev3/internal/domain/domaintest"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestNewBaseEnnoblement(t *testing.T) {
	t.Parallel()

	validBaseEnnoblement := domaintest.NewBaseEnnoblement(t)

	type args struct {
		villageID  int
		newOwnerID int
		newTribeID int
		oldOwnerID int
		oldTribeID int
		points     int
		createdAt  time.Time
	}

	tests := []struct {
		name        string
		args        args
		expectedErr error
	}{
		{
			name: "OK",
			args: args{
				villageID:  validBaseEnnoblement.VillageID(),
				newOwnerID: validBaseEnnoblement.NewOwnerID(),
				newTribeID: validBaseEnnoblement.NewTribeID(),
				oldOwnerID: validBaseEnnoblement.OldOwnerID(),
				oldTribeID: validBaseEnnoblement.OldTribeID(),
				points:     validBaseEnnoblement.Points(),
				createdAt:  validBaseEnnoblement.CreatedAt(),
			},
		},
		{
			name: "ERR: villageID < 1",
			args: args{
				villageID:  0,
				newOwnerID: validBaseEnnoblement.NewOwnerID(),
				newTribeID: validBaseEnnoblement.NewTribeID(),
				oldOwnerID: validBaseEnnoblement.OldOwnerID(),
				oldTribeID: validBaseEnnoblement.OldTribeID(),
				points:     validBaseEnnoblement.Points(),
				createdAt:  validBaseEnnoblement.CreatedAt(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseEnnoblement",
				Field: "villageID",
				Err: domain.MinGreaterEqualError{
					Min:     1,
					Current: 0,
				},
			},
		},
		{
			name: "ERR: newOwnerID < 0",
			args: args{
				villageID:  validBaseEnnoblement.VillageID(),
				newOwnerID: -1,
				newTribeID: validBaseEnnoblement.NewTribeID(),
				oldOwnerID: validBaseEnnoblement.OldOwnerID(),
				oldTribeID: validBaseEnnoblement.OldTribeID(),
				points:     validBaseEnnoblement.Points(),
				createdAt:  validBaseEnnoblement.CreatedAt(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseEnnoblement",
				Field: "newOwnerID",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: newTribeID < 0",
			args: args{
				villageID:  validBaseEnnoblement.VillageID(),
				newOwnerID: validBaseEnnoblement.NewOwnerID(),
				newTribeID: -1,
				oldOwnerID: validBaseEnnoblement.OldOwnerID(),
				oldTribeID: validBaseEnnoblement.OldTribeID(),
				points:     validBaseEnnoblement.Points(),
				createdAt:  validBaseEnnoblement.CreatedAt(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseEnnoblement",
				Field: "newTribeID",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: oldOwnerID < 0",
			args: args{
				villageID:  validBaseEnnoblement.VillageID(),
				newOwnerID: validBaseEnnoblement.NewOwnerID(),
				newTribeID: validBaseEnnoblement.NewTribeID(),
				oldOwnerID: -1,
				oldTribeID: validBaseEnnoblement.OldTribeID(),
				points:     validBaseEnnoblement.Points(),
				createdAt:  validBaseEnnoblement.CreatedAt(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseEnnoblement",
				Field: "oldOwnerID",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: oldTribeID < 0",
			args: args{
				villageID:  validBaseEnnoblement.VillageID(),
				newOwnerID: validBaseEnnoblement.NewOwnerID(),
				newTribeID: validBaseEnnoblement.NewTribeID(),
				oldOwnerID: validBaseEnnoblement.OldOwnerID(),
				oldTribeID: -1,
				points:     validBaseEnnoblement.Points(),
				createdAt:  validBaseEnnoblement.CreatedAt(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseEnnoblement",
				Field: "oldTribeID",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: points < 0",
			args: args{
				villageID:  validBaseEnnoblement.VillageID(),
				newOwnerID: validBaseEnnoblement.NewOwnerID(),
				newTribeID: validBaseEnnoblement.NewTribeID(),
				oldOwnerID: validBaseEnnoblement.OldOwnerID(),
				oldTribeID: validBaseEnnoblement.OldTribeID(),
				points:     -1,
				createdAt:  validBaseEnnoblement.CreatedAt(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseEnnoblement",
				Field: "points",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
	}

	for _, tt := range tests {
		tt := tt

		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			res, err := domain.NewBaseEnnoblement(
				tt.args.villageID,
				tt.args.newOwnerID,
				tt.args.newTribeID,
				tt.args.oldOwnerID,
				tt.args.oldTribeID,
				tt.args.points,
				tt.args.createdAt,
			)
			require.ErrorIs(t, err, tt.expectedErr)
			if tt.expectedErr != nil {
				return
			}
			assert.Equal(t, tt.args.villageID, res.VillageID())
			assert.Equal(t, tt.args.newOwnerID, res.NewOwnerID())
			assert.Equal(t, tt.args.newTribeID, res.NewTribeID())
			assert.Equal(t, tt.args.oldOwnerID, res.OldOwnerID())
			assert.Equal(t, tt.args.oldTribeID, res.OldTribeID())
			assert.Equal(t, tt.args.points, res.Points())
			assert.Equal(t, tt.args.createdAt, res.CreatedAt())
		})
	}
}
