package domain_test

import (
	"net/url"
	"slices"
	"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 TestNewBaseServer(t *testing.T) {
	t.Parallel()

	validBaseServer := domaintest.NewBaseServer(t)

	type args struct {
		key  string
		url  *url.URL
		open bool
	}

	type test struct {
		name        string
		args        args
		expectedErr error
	}

	tests := []test{
		{
			name: "OK",
			args: args{
				key:  validBaseServer.Key(),
				url:  validBaseServer.URL(),
				open: validBaseServer.Open(),
			},
		},
		{
			name: "ERR: url can't be nil",
			args: args{
				key:  validBaseServer.Key(),
				url:  nil,
				open: validBaseServer.Open(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseServer",
				Field: "url",
				Err:   domain.ErrNil,
			},
		},
	}

	for _, serverKeyTest := range newServerKeyValidationTests() {
		tests = append(tests, test{
			name: serverKeyTest.name,
			args: args{
				key:  serverKeyTest.key,
				url:  validBaseServer.URL(),
				open: validBaseServer.Open(),
			},
			expectedErr: domain.ValidationError{
				Model: "BaseServer",
				Field: "key",
				Err:   serverKeyTest.expectedErr,
			},
		})
	}

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

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

			res, err := domain.NewBaseServer(tt.args.key, tt.args.url, tt.args.open)
			require.ErrorIs(t, err, tt.expectedErr)
			if tt.expectedErr != nil {
				return
			}
			assert.Equal(t, tt.args.key, res.Key())
			assert.Equal(t, tt.args.url, res.URL())
			assert.Equal(t, tt.args.open, res.Open())
		})
	}
}

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

	servers := domain.BaseServers{
		domaintest.NewBaseServer(t),
		domaintest.NewBaseServer(t),
		domaintest.NewBaseServer(t),
		domaintest.NewBaseServer(t),
	}

	special := domain.Servers{
		domaintest.NewServer(t, func(cfg *domaintest.ServerConfig) {
			cfg.Key = servers[0].Key()
			cfg.Special = true
		}),
		domaintest.NewServer(t, func(cfg *domaintest.ServerConfig) {
			cfg.Key = servers[2].Key()
			cfg.Special = true
		}),
	}

	res := servers.FilterOutSpecial(special)
	for _, s := range servers {
		if slices.ContainsFunc(special, func(server domain.Server) bool {
			return server.Key() == s.Key()
		}) {
			assert.NotContains(t, res, s)
			continue
		}

		assert.Contains(t, res, s)
	}
}
