package domain_test

import (
	"testing"

	"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 TestNewOpponentsDefeated(t *testing.T) {
	t.Parallel()

	validOD := domaintest.NewOpponentsDefeated(t)

	type args struct {
		rankAtt    int
		scoreAtt   int
		rankDef    int
		scoreDef   int
		rankSup    int
		scoreSup   int
		rankTotal  int
		scoreTotal int
	}

	tests := []struct {
		name        string
		args        args
		expectedErr error
	}{
		{
			name: "OK",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    validOD.RankDef(),
				scoreDef:   validOD.ScoreDef(),
				rankSup:    validOD.RankSup(),
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  validOD.RankTotal(),
				scoreTotal: validOD.ScoreTotal(),
			},
		},
		{
			name: "ERR: rankAtt < 0",
			args: args{
				rankAtt:    -1,
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    validOD.RankDef(),
				scoreDef:   validOD.ScoreDef(),
				rankSup:    validOD.RankSup(),
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  validOD.RankTotal(),
				scoreTotal: validOD.ScoreTotal(),
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "rankAtt",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: scoreAtt < 0",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   -1,
				rankDef:    validOD.RankDef(),
				scoreDef:   validOD.ScoreDef(),
				rankSup:    validOD.RankSup(),
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  validOD.RankTotal(),
				scoreTotal: validOD.ScoreTotal(),
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "scoreAtt",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: rankDef < 0",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    -1,
				scoreDef:   validOD.ScoreDef(),
				rankSup:    validOD.RankSup(),
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  validOD.RankTotal(),
				scoreTotal: validOD.ScoreTotal(),
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "rankDef",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: scoreDef < 0",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    validOD.RankDef(),
				scoreDef:   -1,
				rankSup:    validOD.RankSup(),
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  validOD.RankTotal(),
				scoreTotal: validOD.ScoreTotal(),
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "scoreDef",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: rankSup < 0",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    validOD.RankDef(),
				scoreDef:   validOD.ScoreDef(),
				rankSup:    -1,
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  validOD.RankTotal(),
				scoreTotal: validOD.ScoreTotal(),
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "rankSup",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: scoreSup < 0",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    validOD.RankDef(),
				scoreDef:   validOD.ScoreDef(),
				rankSup:    validOD.RankSup(),
				scoreSup:   -1,
				rankTotal:  validOD.RankTotal(),
				scoreTotal: validOD.ScoreTotal(),
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "scoreSup",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: rankTotal < 0",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    validOD.RankDef(),
				scoreDef:   validOD.ScoreDef(),
				rankSup:    validOD.RankSup(),
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  -1,
				scoreTotal: validOD.ScoreTotal(),
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "rankTotal",
				Err: domain.MinGreaterEqualError{
					Min:     0,
					Current: -1,
				},
			},
		},
		{
			name: "ERR: scoreTotal < 0",
			args: args{
				rankAtt:    validOD.RankAtt(),
				scoreAtt:   validOD.ScoreAtt(),
				rankDef:    validOD.RankDef(),
				scoreDef:   validOD.ScoreDef(),
				rankSup:    validOD.RankSup(),
				scoreSup:   validOD.ScoreSup(),
				rankTotal:  validOD.RankTotal(),
				scoreTotal: -1,
			},
			expectedErr: domain.ValidationError{
				Model: "OpponentsDefeated",
				Field: "scoreTotal",
				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.NewOpponentsDefeated(
				tt.args.rankAtt,
				tt.args.scoreAtt,
				tt.args.rankDef,
				tt.args.scoreDef,
				tt.args.rankSup,
				tt.args.scoreSup,
				tt.args.rankTotal,
				tt.args.scoreTotal,
			)
			require.ErrorIs(t, err, tt.expectedErr)
			if tt.expectedErr != nil {
				return
			}
			assert.Equal(t, tt.args.rankAtt, res.RankAtt())
			assert.Equal(t, tt.args.scoreAtt, res.ScoreAtt())
			assert.Equal(t, tt.args.rankDef, res.RankDef())
			assert.Equal(t, tt.args.scoreDef, res.ScoreDef())
			assert.Equal(t, tt.args.rankSup, res.RankSup())
			assert.Equal(t, tt.args.scoreSup, res.ScoreSup())
			assert.Equal(t, tt.args.rankTotal, res.RankTotal())
			assert.Equal(t, tt.args.scoreTotal, res.ScoreTotal())
		})
	}
}
