package adapter_test

import (
	"cmp"
	"context"
	"slices"
	"testing"

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

func testVersionRepository(t *testing.T, newRepos func(t *testing.T) repositories) {
	t.Helper()

	ctx := context.Background()

	t.Run("List & ListCount", func(t *testing.T) {
		t.Parallel()

		repos := newRepos(t)

		tests := []struct {
			name           string
			params         func(t *testing.T) domain.ListVersionsParams
			assertVersions func(t *testing.T, versions domain.Versions)
			assertError    func(t *testing.T, err error)
			assertTotal    func(t *testing.T, total int)
		}{
			{
				name: "OK: default params",
				params: func(t *testing.T) domain.ListVersionsParams {
					t.Helper()
					return domain.NewListVersionsParams()
				},
				assertVersions: func(t *testing.T, versions domain.Versions) {
					t.Helper()
					assert.NotEmpty(t, len(versions))
					assert.True(t, slices.IsSortedFunc(versions, func(a, b domain.Version) int {
						return cmp.Compare(a.Code(), b.Code())
					}))
				},
				assertError: func(t *testing.T, err error) {
					t.Helper()
					require.NoError(t, err)
				},
				assertTotal: func(t *testing.T, total int) {
					t.Helper()
					assert.NotEmpty(t, total)
				},
			},
			{
				name: "OK: sort=[code DESC]",
				params: func(t *testing.T) domain.ListVersionsParams {
					t.Helper()
					params := domain.NewListVersionsParams()
					require.NoError(t, params.SetSort([]domain.VersionSort{domain.VersionSortCodeDESC}))
					return params
				},
				assertVersions: func(t *testing.T, versions domain.Versions) {
					t.Helper()
					assert.NotEmpty(t, len(versions))
					assert.True(t, slices.IsSortedFunc(versions, func(a, b domain.Version) int {
						return cmp.Compare(a.Code(), b.Code()) * -1
					}))
				},
				assertError: func(t *testing.T, err error) {
					t.Helper()
					require.NoError(t, err)
				},
				assertTotal: func(t *testing.T, total int) {
					t.Helper()
					assert.NotEmpty(t, total)
				},
			},
		}

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

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

				params := tt.params(t)

				res, err := repos.version.List(ctx, params)
				tt.assertError(t, err)
				tt.assertVersions(t, res)

				res, count, err := repos.version.ListCount(ctx, params)
				tt.assertError(t, err)
				tt.assertVersions(t, res)
				tt.assertTotal(t, count)
			})
		}
	})
}
