🏡 index : quine-global/quintodrome.git

package tests

import (
	"context"
	"encoding/base64"
	"fmt"
	"strings"
	"time"

	"github.com/navidrome/navidrome/model"
)

func CreateMockUserRepo() *MockedUserRepo {
	return &MockedUserRepo{
		Data:          map[string]*model.User{},
		UserLibraries: map[string][]int{},
	}
}

type MockedUserRepo struct {
	model.UserRepository
	Error         error
	Data          map[string]*model.User
	UserLibraries map[string][]int // userID -> libraryIDs
}

func (u *MockedUserRepo) CountAll(_ context.Context, qo ...model.QueryOptions) (int64, error) {
	if u.Error != nil {
		return 0, u.Error
	}
	return int64(len(u.Data)), nil
}

func (u *MockedUserRepo) Put(_ context.Context, usr *model.User) error {
	if u.Error != nil {
		return u.Error
	}
	if usr.ID == "" {
		usr.ID = base64.StdEncoding.EncodeToString([]byte(usr.UserName))
	}
	usr.Password = usr.NewPassword
	u.Data[strings.ToLower(usr.UserName)] = usr
	return nil
}

func (u *MockedUserRepo) FindByUsername(_ context.Context, username string) (*model.User, error) {
	if u.Error != nil {
		return nil, u.Error
	}
	usr, ok := u.Data[strings.ToLower(username)]
	if !ok {
		return nil, model.ErrNotFound
	}
	return usr, nil
}

func (u *MockedUserRepo) FindByUsernameWithPassword(ctx context.Context, username string) (*model.User, error) {
	return u.FindByUsername(ctx, username)
}

func (u *MockedUserRepo) FindFirstAdmin(_ context.Context) (*model.User, error) {
	if u.Error != nil {
		return nil, u.Error
	}
	for _, usr := range u.Data {
		if usr.IsAdmin {
			return usr, nil
		}
	}
	return nil, model.ErrNotFound
}

func (u *MockedUserRepo) Get(_ context.Context, id string) (*model.User, error) {
	if u.Error != nil {
		return nil, u.Error
	}
	for _, usr := range u.Data {
		if usr.ID == id {
			return usr, nil
		}
	}
	return nil, model.ErrNotFound
}

func (u *MockedUserRepo) GetAll(_ context.Context, options ...model.QueryOptions) (model.Users, error) {
	if u.Error != nil {
		return nil, u.Error
	}
	var users model.Users
	for _, usr := range u.Data {
		users = append(users, *usr)
	}
	return users, nil
}

func (u *MockedUserRepo) UpdateLastLoginAt(_ context.Context, id string) error {
	for _, usr := range u.Data {
		if usr.ID == id {
			usr.LastLoginAt = new(time.Now())
			return nil
		}
	}
	return u.Error
}

func (u *MockedUserRepo) UpdateLastAccessAt(_ context.Context, id string) error {
	for _, usr := range u.Data {
		if usr.ID == id {
			usr.LastAccessAt = new(time.Now())
			return nil
		}
	}
	return u.Error
}

// Library association methods - mock implementations

func (u *MockedUserRepo) GetUserLibraries(_ context.Context, userID string) (model.Libraries, error) {
	if u.Error != nil {
		return nil, u.Error
	}
	libraryIDs, exists := u.UserLibraries[userID]
	if !exists {
		return model.Libraries{}, nil
	}

	// Mock: Create libraries based on IDs
	var libraries model.Libraries
	for _, id := range libraryIDs {
		libraries = append(libraries, model.Library{
			ID:   id,
			Name: fmt.Sprintf("Test Library %d", id),
			Path: fmt.Sprintf("/music/library%d", id),
		})
	}
	return libraries, nil
}

func (u *MockedUserRepo) SetUserLibraries(_ context.Context, userID string, libraryIDs []int) error {
	if u.Error != nil {
		return u.Error
	}
	if u.UserLibraries == nil {
		u.UserLibraries = make(map[string][]int)
	}
	u.UserLibraries[userID] = libraryIDs
	return nil
}

func (u *MockedUserRepo) Delete(_ context.Context, ids ...string) error {
	if u.Error != nil {
		return u.Error
	}
	for _, id := range ids {
		if err := u.deleteOne(id); err != nil {
			return err
		}
	}
	return nil
}

func (u *MockedUserRepo) deleteOne(id string) error {
	for key, usr := range u.Data {
		if usr.ID == id {
			delete(u.Data, key)
			delete(u.UserLibraries, id)
			return nil
		}
	}
	return model.ErrNotFound
}

func (u *MockedUserRepo) Save(ctx context.Context, usr *model.User) (string, error) {
	if err := u.Put(ctx, usr); err != nil {
		return "", err
	}
	return usr.ID, nil
}

func (u *MockedUserRepo) Update(ctx context.Context, id string, entity model.User, _ ...string) error {
	if u.Error != nil {
		return u.Error
	}
	entity.ID = id
	return u.Put(ctx, &entity)
}