package channelserver

import (
	"errors"
	"time"
)

// errNotFound is a sentinel for mock repos that simulate "not found".
var errNotFound = errors.New("not found")

// --- mockAchievementRepo ---

type mockAchievementRepo struct {
	scores          [33]int32
	ensureCalled    bool
	ensureErr       error
	getScoresErr    error
	incrementErr    error
	incrementedID   uint8
	displayedLevels []byte
	displayedErr    error
	savedLevels     []byte
	saveLevelsErr   error
}

func (m *mockAchievementRepo) EnsureExists(_ uint32) error {
	m.ensureCalled = true
	return m.ensureErr
}

func (m *mockAchievementRepo) GetAllScores(_ uint32) ([33]int32, error) {
	return m.scores, m.getScoresErr
}

func (m *mockAchievementRepo) IncrementScore(_ uint32, id uint8) error {
	m.incrementedID = id
	return m.incrementErr
}

func (m *mockAchievementRepo) GetDisplayedLevels(_ uint32) ([]byte, error) {
	return m.displayedLevels, m.displayedErr
}

func (m *mockAchievementRepo) SaveDisplayedLevels(_ uint32, levels []byte) error {
	m.savedLevels = levels
	return m.saveLevelsErr
}

// --- mockMailRepo ---

type mockMailRepo struct {
	mails          []Mail
	mailByID       map[int]*Mail
	listErr        error
	getByIDErr     error
	markReadCalled int
	markDeletedID  int
	lockID         int
	lockValue      bool
	itemReceivedID int
	sentMails      []sentMailRecord
	sendErr        error
}

type sentMailRecord struct {
	senderID, recipientID          uint32
	subject, body                  string
	itemID, itemAmount             uint16
	isGuildInvite, isSystemMessage bool
}

func (m *mockMailRepo) GetListForCharacter(_ uint32) ([]Mail, error) {
	return m.mails, m.listErr
}

func (m *mockMailRepo) GetByID(id int) (*Mail, error) {
	if m.getByIDErr != nil {
		return nil, m.getByIDErr
	}
	if mail, ok := m.mailByID[id]; ok {
		return mail, nil
	}
	return nil, errNotFound
}

func (m *mockMailRepo) MarkRead(id int) error {
	m.markReadCalled = id
	return nil
}

func (m *mockMailRepo) MarkDeleted(id int) error {
	m.markDeletedID = id
	return nil
}

func (m *mockMailRepo) SetLocked(id int, locked bool) error {
	m.lockID = id
	m.lockValue = locked
	return nil
}

func (m *mockMailRepo) MarkItemReceived(id int) error {
	m.itemReceivedID = id
	return nil
}

func (m *mockMailRepo) SendMail(senderID, recipientID uint32, subject, body string, itemID, itemAmount uint16, isGuildInvite, isSystemMessage bool) error {
	m.sentMails = append(m.sentMails, sentMailRecord{
		senderID: senderID, recipientID: recipientID,
		subject: subject, body: body,
		itemID: itemID, itemAmount: itemAmount,
		isGuildInvite: isGuildInvite, isSystemMessage: isSystemMessage,
	})
	return m.sendErr
}

// --- mockCharacterRepo ---

type mockCharacterRepo struct {
	ints    map[string]int
	times   map[string]time.Time
	columns map[string][]byte
	strings map[string]string
	bools   map[string]bool

	adjustErr     error
	readErr       error
	saveErr       error
	loadColumnErr error

	// LoadSaveData mock fields
	loadSaveDataID   uint32
	loadSaveDataData []byte
	loadSaveDataNew  bool
	loadSaveDataName string
	loadSaveDataHash []byte
	loadSaveDataErr  error

	// ReadEtcPoints mock fields
	etcBonusQuests uint32
	etcDailyQuests uint32
	etcPromoPoints uint32
	etcPointsErr   error
}

func newMockCharacterRepo() *mockCharacterRepo {
	return &mockCharacterRepo{
		ints:    make(map[string]int),
		times:   make(map[string]time.Time),
		columns: make(map[string][]byte),
		strings: make(map[string]string),
		bools:   make(map[string]bool),
	}
}

func (m *mockCharacterRepo) ReadInt(_ uint32, column string) (int, error) {
	if m.readErr != nil {
		return 0, m.readErr
	}
	return m.ints[column], nil
}

func (m *mockCharacterRepo) AdjustInt(_ uint32, column string, delta int) (int, error) {
	if m.adjustErr != nil {
		return 0, m.adjustErr
	}
	m.ints[column] += delta
	return m.ints[column], nil
}

func (m *mockCharacterRepo) SaveInt(_ uint32, column string, value int) error {
	m.ints[column] = value
	return m.saveErr
}

func (m *mockCharacterRepo) ReadTime(_ uint32, column string, defaultVal time.Time) (time.Time, error) {
	if m.readErr != nil {
		return defaultVal, m.readErr
	}
	if t, ok := m.times[column]; ok {
		return t, nil
	}
	return defaultVal, errNotFound
}

func (m *mockCharacterRepo) SaveTime(_ uint32, column string, value time.Time) error {
	m.times[column] = value
	return m.saveErr
}

func (m *mockCharacterRepo) LoadColumn(_ uint32, column string) ([]byte, error) {
	if m.loadColumnErr != nil {
		return nil, m.loadColumnErr
	}
	return m.columns[column], nil
}
func (m *mockCharacterRepo) SaveColumn(_ uint32, column string, data []byte) error {
	m.columns[column] = data
	return m.saveErr
}
func (m *mockCharacterRepo) GetName(_ uint32) (string, error)              { return "TestChar", nil }
func (m *mockCharacterRepo) GetUserID(_ uint32) (uint32, error)            { return 1, nil }
func (m *mockCharacterRepo) UpdateLastLogin(_ uint32, _ int64) error       { return nil }
func (m *mockCharacterRepo) UpdateTimePlayed(_ uint32, _ int) error        { return nil }
func (m *mockCharacterRepo) GetCharIDsByUserID(_ uint32) ([]uint32, error) { return nil, nil }
func (m *mockCharacterRepo) SaveBool(_ uint32, col string, v bool) error {
	m.bools[col] = v
	return nil
}
func (m *mockCharacterRepo) SaveString(_ uint32, col string, v string) error {
	m.strings[col] = v
	return nil
}
func (m *mockCharacterRepo) ReadBool(_ uint32, col string) (bool, error) { return m.bools[col], nil }
func (m *mockCharacterRepo) ReadString(_ uint32, col string) (string, error) {
	return m.strings[col], nil
}
func (m *mockCharacterRepo) LoadColumnWithDefault(_ uint32, col string, def []byte) ([]byte, error) {
	if d, ok := m.columns[col]; ok {
		return d, nil
	}
	return def, nil
}
func (m *mockCharacterRepo) SetDeleted(_ uint32) error                                { return nil }
func (m *mockCharacterRepo) UpdateDailyCafe(_ uint32, _ time.Time, _, _ uint32) error { return nil }
func (m *mockCharacterRepo) ResetDailyQuests(_ uint32) error                          { return nil }
func (m *mockCharacterRepo) ReadEtcPoints(_ uint32) (uint32, uint32, uint32, error) {
	return m.etcBonusQuests, m.etcDailyQuests, m.etcPromoPoints, m.etcPointsErr
}
func (m *mockCharacterRepo) ResetCafeTime(_ uint32, _ time.Time) error { return nil }
func (m *mockCharacterRepo) UpdateGuildPostChecked(_ uint32) error     { return nil }
func (m *mockCharacterRepo) ReadGuildPostChecked(_ uint32) (time.Time, error) {
	return time.Time{}, nil
}
func (m *mockCharacterRepo) SaveMercenary(_ uint32, _ []byte, _ uint32) error    { return nil }
func (m *mockCharacterRepo) UpdateGCPAndPact(_ uint32, _ uint32, _ uint32) error { return nil }
func (m *mockCharacterRepo) FindByRastaID(_ int) (uint32, string, error)         { return 0, "", nil }
func (m *mockCharacterRepo) SaveCharacterData(_ uint32, _ []byte, _, _ uint16, _ bool, _ uint8, _ uint16) error {
	return nil
}
func (m *mockCharacterRepo) SaveHouseData(_ uint32, _ []byte, _, _, _, _, _ []byte) error { return nil }
func (m *mockCharacterRepo) LoadSaveData(_ uint32) (uint32, []byte, bool, string, error) {
	return m.loadSaveDataID, m.loadSaveDataData, m.loadSaveDataNew, m.loadSaveDataName, m.loadSaveDataErr
}
func (m *mockCharacterRepo) SaveBackup(_ uint32, _ int, _ []byte) error       { return nil }
func (m *mockCharacterRepo) GetLastBackupTime(_ uint32) (time.Time, error)    { return time.Time{}, nil }
func (m *mockCharacterRepo) SaveCharacterDataAtomic(_ SaveAtomicParams) error { return nil }
func (m *mockCharacterRepo) LoadSaveDataWithHash(_ uint32) (uint32, []byte, bool, string, []byte, error) {
	return m.loadSaveDataID, m.loadSaveDataData, m.loadSaveDataNew, m.loadSaveDataName, m.loadSaveDataHash, m.loadSaveDataErr
}
func (m *mockCharacterRepo) LoadBackupsByRecency(_ uint32) ([]SavedataBackup, error) {
	return []SavedataBackup{}, nil
}

// --- mockGoocooRepo ---

type mockGoocooRepo struct {
	slots        map[uint32][]byte
	ensureCalled bool
	clearCalled  []uint32
	savedSlots   map[uint32][]byte
}

func newMockGoocooRepo() *mockGoocooRepo {
	return &mockGoocooRepo{
		slots:      make(map[uint32][]byte),
		savedSlots: make(map[uint32][]byte),
	}
}

func (m *mockGoocooRepo) EnsureExists(_ uint32) error {
	m.ensureCalled = true
	return nil
}

func (m *mockGoocooRepo) GetSlot(_ uint32, slot uint32) ([]byte, error) {
	if data, ok := m.slots[slot]; ok {
		return data, nil
	}
	return nil, nil
}

func (m *mockGoocooRepo) ClearSlot(_ uint32, slot uint32) error {
	m.clearCalled = append(m.clearCalled, slot)
	delete(m.slots, slot)
	return nil
}

func (m *mockGoocooRepo) SaveSlot(_ uint32, slot uint32, data []byte) error {
	m.savedSlots[slot] = data
	return nil
}

// --- mockGuildRepo ---

type mockGuildRepo struct {
	// Core data
	guild   *Guild
	members []*GuildMember

	// Configurable errors
	getErr          error
	getMembersErr   error
	saveErr         error
	saveMemberErr   error
	disbandErr      error
	acceptErr       error
	rejectErr       error
	removeErr       error
	createAppErr    error
	getMemberErr    error
	hasAppResult    bool
	hasAppErr       error
	hasInviteResult bool
	hasInviteErr    error
	listPostsErr    error
	createPostErr   error
	deletePostErr   error

	// State tracking
	disbandedID         uint32
	removedCharID       uint32
	acceptedCharID      uint32
	rejectedCharID      uint32
	acceptInviteCharID  uint32
	declineInviteCharID uint32
	savedGuild          *Guild
	savedMembers        []*GuildMember
	createdAppArgs      []interface{}
	createdPost         []interface{}
	deletedPostID       uint32

	// Alliance
	alliance              *GuildAlliance
	getAllianceErr        error
	createAllianceErr     error
	deleteAllianceErr     error
	removeAllyErr         error
	setAllianceRecruitErr error
	deletedAllianceID     uint32
	removedAllyArgs       []uint32
	allianceRecruitingSet *bool

	// Cooking
	meals         []*GuildMeal
	listMealsErr  error
	createdMealID uint32
	createMealErr error
	updateMealErr error

	// Adventure
	adventures      []*GuildAdventure
	listAdvErr      error
	createAdvErr    error
	collectAdvID    uint32
	chargeAdvID     uint32
	chargeAdvAmount uint32

	// Treasure hunt
	pendingHunt   *TreasureHunt
	guildHunts    []*TreasureHunt
	listHuntsErr  error
	acquireHuntID uint32
	reportHuntID  uint32
	collectHuntID uint32
	claimHuntID   uint32
	createHuntErr error

	// Hunt data
	guildKills     []*GuildKill
	listKillsErr   error
	countKills     int
	countKillsErr  error
	claimBoxCalled bool

	// Data
	membership  *GuildMember
	application *GuildApplication
	posts       []*MessageBoardPost
}

func (m *mockGuildRepo) GetByID(guildID uint32) (*Guild, error) {
	if m.getErr != nil {
		return nil, m.getErr
	}
	if m.guild != nil && m.guild.ID == guildID {
		return m.guild, nil
	}
	return nil, errNotFound
}

func (m *mockGuildRepo) GetByCharID(_ uint32) (*Guild, error) {
	if m.getErr != nil {
		return nil, m.getErr
	}
	return m.guild, nil
}

func (m *mockGuildRepo) GetMembers(_ uint32, _ bool) ([]*GuildMember, error) {
	if m.getMembersErr != nil {
		return nil, m.getMembersErr
	}
	return m.members, nil
}

func (m *mockGuildRepo) GetCharacterMembership(_ uint32) (*GuildMember, error) {
	if m.getMemberErr != nil {
		return nil, m.getMemberErr
	}
	return m.membership, nil
}

func (m *mockGuildRepo) Save(guild *Guild) error {
	m.savedGuild = guild
	return m.saveErr
}

func (m *mockGuildRepo) SaveMember(member *GuildMember) error {
	m.savedMembers = append(m.savedMembers, member)
	return m.saveMemberErr
}

func (m *mockGuildRepo) Disband(guildID uint32) error {
	m.disbandedID = guildID
	return m.disbandErr
}

func (m *mockGuildRepo) RemoveCharacter(charID uint32) error {
	m.removedCharID = charID
	return m.removeErr
}

func (m *mockGuildRepo) AcceptApplication(_, charID uint32) error {
	m.acceptedCharID = charID
	return m.acceptErr
}

func (m *mockGuildRepo) RejectApplication(_, charID uint32) error {
	m.rejectedCharID = charID
	return m.rejectErr
}

func (m *mockGuildRepo) CreateApplication(guildID, charID, actorID uint32, appType GuildApplicationType) error {
	m.createdAppArgs = []interface{}{guildID, charID, actorID, appType}
	return m.createAppErr
}

func (m *mockGuildRepo) HasApplication(_, _ uint32) (bool, error) {
	return m.hasAppResult, m.hasAppErr
}

func (m *mockGuildRepo) GetApplication(_, _ uint32, _ GuildApplicationType) (*GuildApplication, error) {
	return m.application, nil
}

func (m *mockGuildRepo) ListPosts(_ uint32, _ int) ([]*MessageBoardPost, error) {
	if m.listPostsErr != nil {
		return nil, m.listPostsErr
	}
	return m.posts, nil
}

func (m *mockGuildRepo) CreatePost(guildID, authorID, stampID uint32, postType int, title, body string, maxPosts int) error {
	m.createdPost = []interface{}{guildID, authorID, stampID, postType, title, body, maxPosts}
	return m.createPostErr
}

func (m *mockGuildRepo) DeletePost(postID uint32) error {
	m.deletedPostID = postID
	return m.deletePostErr
}

func (m *mockGuildRepo) GetAllianceByID(_ uint32) (*GuildAlliance, error) {
	return m.alliance, m.getAllianceErr
}

func (m *mockGuildRepo) CreateAlliance(_ string, _ uint32) error {
	return m.createAllianceErr
}

func (m *mockGuildRepo) DeleteAlliance(id uint32) error {
	m.deletedAllianceID = id
	return m.deleteAllianceErr
}

func (m *mockGuildRepo) SetAllianceRecruiting(_ uint32, recruiting bool) error {
	m.allianceRecruitingSet = &recruiting
	return m.setAllianceRecruitErr
}

func (m *mockGuildRepo) RemoveGuildFromAlliance(allyID, guildID, sub1, sub2 uint32) error {
	m.removedAllyArgs = []uint32{allyID, guildID, sub1, sub2}
	return m.removeAllyErr
}

func (m *mockGuildRepo) ListMeals(_ uint32) ([]*GuildMeal, error) {
	return m.meals, m.listMealsErr
}

func (m *mockGuildRepo) CreateMeal(_, _, _ uint32, _ time.Time) (uint32, error) {
	return m.createdMealID, m.createMealErr
}

func (m *mockGuildRepo) UpdateMeal(_, _, _ uint32, _ time.Time) error {
	return m.updateMealErr
}

func (m *mockGuildRepo) ListAdventures(_ uint32) ([]*GuildAdventure, error) {
	return m.adventures, m.listAdvErr
}

func (m *mockGuildRepo) CreateAdventure(_, _ uint32, _, _ int64) error {
	return m.createAdvErr
}

func (m *mockGuildRepo) CreateAdventureWithCharge(_, _, _ uint32, _, _ int64) error {
	return m.createAdvErr
}

func (m *mockGuildRepo) CollectAdventure(id uint32, _ uint32) error {
	m.collectAdvID = id
	return nil
}

func (m *mockGuildRepo) ChargeAdventure(id uint32, amount uint32) error {
	m.chargeAdvID = id
	m.chargeAdvAmount = amount
	return nil
}

func (m *mockGuildRepo) GetPendingHunt(_ uint32) (*TreasureHunt, error) {
	return m.pendingHunt, nil
}

func (m *mockGuildRepo) ListGuildHunts(_, _ uint32) ([]*TreasureHunt, error) {
	return m.guildHunts, m.listHuntsErr
}

func (m *mockGuildRepo) CreateHunt(_, _, _, _ uint32, _ []byte, _ string) error {
	return m.createHuntErr
}

func (m *mockGuildRepo) AcquireHunt(id uint32) error {
	m.acquireHuntID = id
	return nil
}

func (m *mockGuildRepo) RegisterHuntReport(id, _ uint32) error {
	m.reportHuntID = id
	return nil
}

func (m *mockGuildRepo) CollectHunt(id uint32) error {
	m.collectHuntID = id
	return nil
}

func (m *mockGuildRepo) ClaimHuntReward(id, _ uint32) error {
	m.claimHuntID = id
	return nil
}

func (m *mockGuildRepo) ClaimHuntBox(_ uint32, _ time.Time) error {
	m.claimBoxCalled = true
	return nil
}

func (m *mockGuildRepo) ListGuildKills(_, _ uint32) ([]*GuildKill, error) {
	return m.guildKills, m.listKillsErr
}

func (m *mockGuildRepo) CountGuildKills(_, _ uint32) (int, error) {
	return m.countKills, m.countKillsErr
}

// No-op stubs for remaining GuildRepo interface methods.
func (m *mockGuildRepo) ListAll() ([]*Guild, error)                                   { return nil, nil }
func (m *mockGuildRepo) Create(_ uint32, _ string) (int32, error)                     { return 0, nil }
func (m *mockGuildRepo) CreateInviteWithMail(_, _, _, _, _ uint32, _, _ string) error { return nil }
func (m *mockGuildRepo) HasInvite(_, _ uint32) (bool, error) {
	return m.hasInviteResult, m.hasInviteErr
}
func (m *mockGuildRepo) CancelInvite(_ uint32) error { return nil }
func (m *mockGuildRepo) AcceptInvite(_, charID uint32) error {
	m.acceptInviteCharID = charID
	return m.acceptErr
}
func (m *mockGuildRepo) DeclineInvite(_, charID uint32) error {
	m.declineInviteCharID = charID
	return m.rejectErr
}
func (m *mockGuildRepo) ArrangeCharacters(_ []uint32) error                        { return nil }
func (m *mockGuildRepo) GetItemBox(_ uint32) ([]byte, error)                       { return nil, nil }
func (m *mockGuildRepo) SaveItemBox(_ uint32, _ []byte) error                      { return nil }
func (m *mockGuildRepo) SetRecruiting(_ uint32, _ bool) error                      { return nil }
func (m *mockGuildRepo) SetPugiOutfits(_ uint32, _ uint32) error                   { return nil }
func (m *mockGuildRepo) SetRecruiter(_ uint32, _ bool) error                       { return nil }
func (m *mockGuildRepo) AddMemberDailyRP(_ uint32, _ uint16) error                 { return nil }
func (m *mockGuildRepo) ExchangeEventRP(_ uint32, _ uint16) (uint32, error)        { return 0, nil }
func (m *mockGuildRepo) AddRankRP(_ uint32, _ uint16) error                        { return nil }
func (m *mockGuildRepo) AddEventRP(_ uint32, _ uint16) error                       { return nil }
func (m *mockGuildRepo) GetRoomRP(_ uint32) (uint16, error)                        { return 0, nil }
func (m *mockGuildRepo) SetRoomRP(_ uint32, _ uint16) error                        { return nil }
func (m *mockGuildRepo) AddRoomRP(_ uint32, _ uint16) error                        { return nil }
func (m *mockGuildRepo) SetRoomExpiry(_ uint32, _ time.Time) error                 { return nil }
func (m *mockGuildRepo) UpdatePost(_ uint32, _, _ string) error                    { return nil }
func (m *mockGuildRepo) UpdatePostStamp(_, _ uint32) error                         { return nil }
func (m *mockGuildRepo) GetPostLikedBy(_ uint32) (string, error)                   { return "", nil }
func (m *mockGuildRepo) SetPostLikedBy(_ uint32, _ string) error                   { return nil }
func (m *mockGuildRepo) CountNewPosts(_ uint32, _ time.Time) (int, error)          { return 0, nil }
func (m *mockGuildRepo) ListAlliances() ([]*GuildAlliance, error)                  { return nil, nil }
func (m *mockGuildRepo) ClearTreasureHunt(_ uint32) error                          { return nil }
func (m *mockGuildRepo) InsertKillLog(_ uint32, _ int, _ uint8, _ time.Time) error { return nil }
func (m *mockGuildRepo) ListInvites(_ uint32) ([]*GuildInvite, error)              { return nil, nil }
func (m *mockGuildRepo) RolloverDailyRP(_ uint32, _ time.Time) error               { return nil }
func (m *mockGuildRepo) AddWeeklyBonusUsers(_ uint32, _ uint8) error               { return nil }
func (m *mockGuildRepo) FindOrCreateReturnGuild(_ uint8, _ string) (uint32, error) {
	return 1, nil
}
func (m *mockGuildRepo) AddMember(_, _ uint32) error { return nil }

// --- mockUserRepoForItems ---

type mockUserRepoForItems struct {
	itemBoxData []byte
	itemBoxErr  error
	setData     []byte
}

func (m *mockUserRepoForItems) GetItemBox(_ uint32) ([]byte, error) {
	return m.itemBoxData, m.itemBoxErr
}

func (m *mockUserRepoForItems) SetItemBox(_ uint32, data []byte) error {
	m.setData = data
	return nil
}

// Stub all other UserRepo methods.
func (m *mockUserRepoForItems) GetGachaPoints(_ uint32) (uint32, uint32, uint32, error) {
	return 0, 0, 0, nil
}
func (m *mockUserRepoForItems) GetTrialCoins(_ uint32) (uint16, error)        { return 0, nil }
func (m *mockUserRepoForItems) DeductTrialCoins(_ uint32, _ uint32) error     { return nil }
func (m *mockUserRepoForItems) DeductPremiumCoins(_ uint32, _ uint32) error   { return nil }
func (m *mockUserRepoForItems) AddPremiumCoins(_ uint32, _ uint32) error      { return nil }
func (m *mockUserRepoForItems) AddTrialCoins(_ uint32, _ uint32) error        { return nil }
func (m *mockUserRepoForItems) DeductFrontierPoints(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AddFrontierPoints(_ uint32, _ uint32) error    { return nil }
func (m *mockUserRepoForItems) AdjustFrontierPointsDeduct(_ uint32, _ int) (uint32, error) {
	return 0, nil
}
func (m *mockUserRepoForItems) AdjustFrontierPointsCredit(_ uint32, _ int) (uint32, error) {
	return 0, nil
}
func (m *mockUserRepoForItems) AddFrontierPointsFromGacha(_ uint32, _ uint32, _ uint8) error {
	return nil
}
func (m *mockUserRepoForItems) GetRights(_ uint32) (uint32, error)              { return 0, nil }
func (m *mockUserRepoForItems) SetRights(_ uint32, _ uint32) error              { return nil }
func (m *mockUserRepoForItems) IsOp(_ uint32) (bool, error)                     { return false, nil }
func (m *mockUserRepoForItems) SetLastCharacter(_ uint32, _ uint32) error       { return nil }
func (m *mockUserRepoForItems) GetTimer(_ uint32) (bool, error)                 { return false, nil }
func (m *mockUserRepoForItems) SetTimer(_ uint32, _ bool) error                 { return nil }
func (m *mockUserRepoForItems) CountByPSNID(_ string) (int, error)              { return 0, nil }
func (m *mockUserRepoForItems) SetPSNID(_ uint32, _ string) error               { return nil }
func (m *mockUserRepoForItems) GetDiscordToken(_ uint32) (string, error)        { return "", nil }
func (m *mockUserRepoForItems) SetDiscordToken(_ uint32, _ string) error        { return nil }
func (m *mockUserRepoForItems) LinkDiscord(_ string, _ string) (string, error)  { return "", nil }
func (m *mockUserRepoForItems) SetPasswordByDiscordID(_ string, _ []byte) error { return nil }
func (m *mockUserRepoForItems) GetByIDAndUsername(_ uint32) (uint32, string, error) {
	return 0, "", nil
}
func (m *mockUserRepoForItems) BanUser(_ uint32, _ *time.Time) error { return nil }
func (m *mockUserRepoForItems) GetLanguage(_ uint32) (string, error) { return "", nil }
func (m *mockUserRepoForItems) SetLanguage(_ uint32, _ string) error { return nil }

// --- mockStampRepoForItems ---

type mockStampRepoForItems struct {
	checkedTime     time.Time
	checkedErr      error
	totals          [2]uint16 // total, redeemed
	totalsErr       error
	initCalled      bool
	incrementCalled bool
	setCalled       bool
	exchangeResult  [2]uint16
	exchangeErr     error
	yearlyResult    [2]uint16
	yearlyErr       error

	// Monthly item fields
	monthlyClaimed    time.Time
	monthlyClaimedErr error
	monthlySetCalled  bool
	monthlySetType    string
}

func (m *mockStampRepoForItems) GetChecked(_ uint32, _ string) (time.Time, error) {
	return m.checkedTime, m.checkedErr
}

func (m *mockStampRepoForItems) Init(_ uint32, _ time.Time) error {
	m.initCalled = true
	return nil
}

func (m *mockStampRepoForItems) SetChecked(_ uint32, _ string, _ time.Time) error {
	m.setCalled = true
	return nil
}

func (m *mockStampRepoForItems) IncrementTotal(_ uint32, _ string) error {
	m.incrementCalled = true
	return nil
}

func (m *mockStampRepoForItems) GetTotals(_ uint32, _ string) (uint16, uint16, error) {
	return m.totals[0], m.totals[1], m.totalsErr
}

func (m *mockStampRepoForItems) ExchangeYearly(_ uint32) (uint16, uint16, error) {
	return m.yearlyResult[0], m.yearlyResult[1], m.yearlyErr
}

func (m *mockStampRepoForItems) Exchange(_ uint32, _ string) (uint16, uint16, error) {
	return m.exchangeResult[0], m.exchangeResult[1], m.exchangeErr
}

func (m *mockStampRepoForItems) GetMonthlyClaimed(_ uint32, _ string) (time.Time, error) {
	return m.monthlyClaimed, m.monthlyClaimedErr
}

func (m *mockStampRepoForItems) SetMonthlyClaimed(_ uint32, monthlyType string, _ time.Time) error {
	m.monthlySetCalled = true
	m.monthlySetType = monthlyType
	return nil
}

// --- mockHouseRepoForItems ---

type mockHouseRepoForItems struct {
	warehouseItems map[uint8][]byte
	setData        map[uint8][]byte
	setErr         error
}

func newMockHouseRepoForItems() *mockHouseRepoForItems {
	return &mockHouseRepoForItems{
		warehouseItems: make(map[uint8][]byte),
		setData:        make(map[uint8][]byte),
	}
}

func (m *mockHouseRepoForItems) GetWarehouseItemData(_ uint32, index uint8) ([]byte, error) {
	return m.warehouseItems[index], nil
}

func (m *mockHouseRepoForItems) SetWarehouseItemData(_ uint32, index uint8, data []byte) error {
	m.setData[index] = data
	return m.setErr
}

func (m *mockHouseRepoForItems) InitializeWarehouse(_ uint32) error { return nil }

// Stub all other HouseRepo methods.
func (m *mockHouseRepoForItems) UpdateInterior(_ uint32, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetHouseByCharID(_ uint32) (HouseData, error) {
	return HouseData{}, nil
}
func (m *mockHouseRepoForItems) SearchHousesByName(_ string) ([]HouseData, error)   { return nil, nil }
func (m *mockHouseRepoForItems) UpdateHouseState(_ uint32, _ uint8, _ string) error { return nil }
func (m *mockHouseRepoForItems) GetHouseAccess(_ uint32) (uint8, string, error)     { return 0, "", nil }
func (m *mockHouseRepoForItems) GetHouseContents(_ uint32) ([]byte, []byte, []byte, []byte, []byte, []byte, []byte, error) {
	return nil, nil, nil, nil, nil, nil, nil, nil
}
func (m *mockHouseRepoForItems) GetMission(_ uint32) ([]byte, error)    { return nil, nil }
func (m *mockHouseRepoForItems) UpdateMission(_ uint32, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetWarehouseNames(_ uint32) ([10]string, [10]string, error) {
	return [10]string{}, [10]string{}, nil
}
func (m *mockHouseRepoForItems) RenameWarehouseBox(_ uint32, _ uint8, _ uint8, _ string) error {
	return nil
}
func (m *mockHouseRepoForItems) GetWarehouseEquipData(_ uint32, _ uint8) ([]byte, error) {
	return nil, nil
}
func (m *mockHouseRepoForItems) SetWarehouseEquipData(_ uint32, _ uint8, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetTitles(_ uint32) ([]Title, error)                     { return nil, nil }
func (m *mockHouseRepoForItems) AcquireTitle(_ uint16, _ uint32) error                   { return nil }

// --- mockSessionRepo ---

type mockSessionRepo struct {
	validateErr error
	bindErr     error
	clearErr    error
	updateErr   error

	boundToken   string
	clearedToken string
}

func (m *mockSessionRepo) ValidateLoginToken(_ string, _ uint32, _ uint32) error {
	return m.validateErr
}
func (m *mockSessionRepo) BindSession(token string, _ uint16, _ uint32) error {
	m.boundToken = token
	return m.bindErr
}
func (m *mockSessionRepo) ClearSession(token string) error {
	m.clearedToken = token
	return m.clearErr
}
func (m *mockSessionRepo) UpdatePlayerCount(_ uint16, _ int) error { return m.updateErr }

// --- mockGachaRepo ---

type mockGachaRepo struct {
	// GetEntryForTransaction
	txItemType   uint8
	txItemNumber uint16
	txRolls      int
	txErr        error

	// GetRewardPool
	rewardPool    []GachaEntry
	rewardPoolErr error

	// GetItemsForEntry
	entryItems    map[uint32][]GachaItem
	entryItemsErr error

	// GetGuaranteedItems
	guaranteedItems []GachaItem

	// Stepup
	stepupStep    uint8
	stepupTime    time.Time
	stepupErr     error
	hasEntryType  bool
	deletedStepup bool
	insertedStep  uint8

	// Box
	boxEntryIDs    []uint32
	boxEntryIDsErr error
	insertedBoxIDs []uint32
	deletedBox     bool

	// Shop
	gachas        []Gacha
	listShopErr   error
	shopType      int
	allEntries    []GachaEntry
	allEntriesErr error
	weightDivisor float64
}

func (m *mockGachaRepo) GetEntryForTransaction(_ uint32, _ uint8) (uint8, uint16, int, error) {
	return m.txItemType, m.txItemNumber, m.txRolls, m.txErr
}
func (m *mockGachaRepo) GetRewardPool(_ uint32) ([]GachaEntry, error) {
	return m.rewardPool, m.rewardPoolErr
}
func (m *mockGachaRepo) GetItemsForEntry(entryID uint32) ([]GachaItem, error) {
	if m.entryItemsErr != nil {
		return nil, m.entryItemsErr
	}
	if m.entryItems != nil {
		return m.entryItems[entryID], nil
	}
	return nil, nil
}
func (m *mockGachaRepo) GetGuaranteedItems(_ uint8, _ uint32) ([]GachaItem, error) {
	return m.guaranteedItems, nil
}
func (m *mockGachaRepo) GetStepupStep(_ uint32, _ uint32) (uint8, error) {
	return m.stepupStep, m.stepupErr
}
func (m *mockGachaRepo) GetStepupWithTime(_ uint32, _ uint32) (uint8, time.Time, error) {
	return m.stepupStep, m.stepupTime, m.stepupErr
}
func (m *mockGachaRepo) HasEntryType(_ uint32, _ uint8) (bool, error) {
	return m.hasEntryType, nil
}
func (m *mockGachaRepo) DeleteStepup(_ uint32, _ uint32) error {
	m.deletedStepup = true
	return nil
}
func (m *mockGachaRepo) InsertStepup(_ uint32, step uint8, _ uint32) error {
	m.insertedStep = step
	return nil
}
func (m *mockGachaRepo) GetBoxEntryIDs(_ uint32, _ uint32) ([]uint32, error) {
	return m.boxEntryIDs, m.boxEntryIDsErr
}
func (m *mockGachaRepo) InsertBoxEntry(_ uint32, entryID uint32, _ uint32) error {
	m.insertedBoxIDs = append(m.insertedBoxIDs, entryID)
	return nil
}
func (m *mockGachaRepo) DeleteBoxEntries(_ uint32, _ uint32) error {
	m.deletedBox = true
	return nil
}
func (m *mockGachaRepo) ListShop() ([]Gacha, error)        { return m.gachas, m.listShopErr }
func (m *mockGachaRepo) GetShopType(_ uint32) (int, error) { return m.shopType, nil }
func (m *mockGachaRepo) GetAllEntries(_ uint32) ([]GachaEntry, error) {
	return m.allEntries, m.allEntriesErr
}
func (m *mockGachaRepo) GetWeightDivisor(_ uint32) (float64, error) { return m.weightDivisor, nil }

// --- mockShopRepo ---

type mockShopRepo struct {
	shopItems       []ShopItem
	shopItemsErr    error
	purchases       []shopPurchaseRecord
	recordErr       error
	fpointQuantity  int
	fpointValue     int
	fpointItemErr   error
	fpointExchanges []FPointExchange
}

type shopPurchaseRecord struct {
	charID, itemHash, quantity uint32
}

func (m *mockShopRepo) GetShopItems(_ uint8, _ uint32, _ uint32) ([]ShopItem, error) {
	return m.shopItems, m.shopItemsErr
}
func (m *mockShopRepo) RecordPurchase(charID, itemHash, quantity uint32) error {
	m.purchases = append(m.purchases, shopPurchaseRecord{charID, itemHash, quantity})
	return m.recordErr
}
func (m *mockShopRepo) GetFpointItem(_ uint32) (int, int, error) {
	return m.fpointQuantity, m.fpointValue, m.fpointItemErr
}
func (m *mockShopRepo) GetFpointExchangeList() ([]FPointExchange, error) {
	return m.fpointExchanges, nil
}

// --- mockUserRepoGacha (UserRepo with configurable gacha fields) ---

type mockUserRepoGacha struct {
	mockUserRepoForItems

	gachaFP, gachaGP, gachaGT uint32
	trialCoins                uint16
	deductTrialErr            error
	deductPremiumErr          error
	deductFPErr               error
	addFPFromGachaErr         error

	fpDeductBalance uint32
	fpDeductErr     error
	fpCreditBalance uint32
	fpCreditErr     error

	setLastCharErr error
	rights         uint32
	rightsErr      error
}

func (m *mockUserRepoGacha) GetGachaPoints(_ uint32) (uint32, uint32, uint32, error) {
	return m.gachaFP, m.gachaGP, m.gachaGT, nil
}
func (m *mockUserRepoGacha) GetTrialCoins(_ uint32) (uint16, error)    { return m.trialCoins, nil }
func (m *mockUserRepoGacha) DeductTrialCoins(_ uint32, _ uint32) error { return m.deductTrialErr }
func (m *mockUserRepoGacha) DeductPremiumCoins(_ uint32, _ uint32) error {
	return m.deductPremiumErr
}
func (m *mockUserRepoGacha) DeductFrontierPoints(_ uint32, _ uint32) error { return m.deductFPErr }
func (m *mockUserRepoGacha) AddFrontierPointsFromGacha(_ uint32, _ uint32, _ uint8) error {
	return m.addFPFromGachaErr
}
func (m *mockUserRepoGacha) AdjustFrontierPointsDeduct(_ uint32, _ int) (uint32, error) {
	return m.fpDeductBalance, m.fpDeductErr
}
func (m *mockUserRepoGacha) AdjustFrontierPointsCredit(_ uint32, _ int) (uint32, error) {
	return m.fpCreditBalance, m.fpCreditErr
}
func (m *mockUserRepoGacha) SetLastCharacter(_ uint32, _ uint32) error { return m.setLastCharErr }
func (m *mockUserRepoGacha) GetRights(_ uint32) (uint32, error)        { return m.rights, m.rightsErr }

// --- mockTowerRepo ---

type mockTowerRepo struct {
	towerData    TowerData
	towerDataErr error
	skills       string
	skillsErr    error
	gems         string
	gemsErr      error
	updatedGems  string

	progress      TenrouiraiProgressData
	progressErr   error
	scores        []TenrouiraiCharScore
	scoresErr     error
	guildRP       uint32
	guildRPErr    error
	page          int
	donated       int
	pageRPErr     error
	advanceErr    error
	advanceCalled bool
	donateErr     error
	donatedRP     uint16
}

func (m *mockTowerRepo) GetTowerData(_ uint32) (TowerData, error)        { return m.towerData, m.towerDataErr }
func (m *mockTowerRepo) GetSkills(_ uint32) (string, error)              { return m.skills, m.skillsErr }
func (m *mockTowerRepo) UpdateSkills(_ uint32, _ string, _ int32) error  { return nil }
func (m *mockTowerRepo) UpdateProgress(_ uint32, _, _, _, _ int32) error { return nil }
func (m *mockTowerRepo) GetGems(_ uint32) (string, error)                { return m.gems, m.gemsErr }
func (m *mockTowerRepo) UpdateGems(_ uint32, gems string) error {
	m.updatedGems = gems
	return nil
}
func (m *mockTowerRepo) GetTenrouiraiProgress(_ uint32) (TenrouiraiProgressData, error) {
	return m.progress, m.progressErr
}
func (m *mockTowerRepo) GetTenrouiraiMissionScores(_ uint32, _ uint8) ([]TenrouiraiCharScore, error) {
	return m.scores, m.scoresErr
}
func (m *mockTowerRepo) GetGuildTowerRP(_ uint32) (uint32, error) { return m.guildRP, m.guildRPErr }
func (m *mockTowerRepo) GetGuildTowerPageAndRP(_ uint32) (int, int, error) {
	return m.page, m.donated, m.pageRPErr
}
func (m *mockTowerRepo) AdvanceTenrouiraiPage(_ uint32) error {
	m.advanceCalled = true
	return m.advanceErr
}
func (m *mockTowerRepo) DonateGuildTowerRP(_ uint32, rp uint16) error {
	m.donatedRP = rp
	return m.donateErr
}

// --- mockFestaRepo ---

type mockFestaRepo struct {
	events     []FestaEvent
	eventsErr  error
	teamSouls  uint32
	teamErr    error
	trials     []FestaTrial
	trialsErr  error
	topGuild   FestaGuildRanking
	topErr     error
	topWindow  FestaGuildRanking
	topWinErr  error
	charSouls  uint32
	charErr    error
	hasClaimed bool
	prizes     []Prize
	prizesErr  error

	cleanupErr     error
	cleanupCalled  bool
	insertErr      error
	insertedStart  uint32
	submitErr      error
	submittedSouls []uint16
}

func (m *mockFestaRepo) CleanupAll() error {
	m.cleanupCalled = true
	return m.cleanupErr
}
func (m *mockFestaRepo) InsertEvent(start uint32) error {
	m.insertedStart = start
	return m.insertErr
}
func (m *mockFestaRepo) GetFestaEvents() ([]FestaEvent, error) { return m.events, m.eventsErr }
func (m *mockFestaRepo) GetTeamSouls(_ string) (uint32, error) { return m.teamSouls, m.teamErr }
func (m *mockFestaRepo) GetTrialsWithMonopoly() ([]FestaTrial, error) {
	return m.trials, m.trialsErr
}
func (m *mockFestaRepo) GetTopGuildForTrial(_ uint16) (FestaGuildRanking, error) {
	return m.topGuild, m.topErr
}
func (m *mockFestaRepo) GetTopGuildInWindow(_, _ uint32) (FestaGuildRanking, error) {
	return m.topWindow, m.topWinErr
}
func (m *mockFestaRepo) GetCharSouls(_ uint32) (uint32, error)  { return m.charSouls, m.charErr }
func (m *mockFestaRepo) HasClaimedMainPrize(_ uint32) bool      { return m.hasClaimed }
func (m *mockFestaRepo) VoteTrial(_ uint32, _ uint32) error     { return nil }
func (m *mockFestaRepo) RegisterGuild(_ uint32, _ string) error { return nil }
func (m *mockFestaRepo) SubmitSouls(_, _ uint32, souls []uint16) error {
	m.submittedSouls = souls
	return m.submitErr
}
func (m *mockFestaRepo) ClaimPrize(_ uint32, _ uint32) error { return nil }
func (m *mockFestaRepo) ListPrizes(_ uint32, _ string) ([]Prize, error) {
	return m.prizes, m.prizesErr
}

// --- mockRengokuRepo ---

type mockRengokuRepo struct {
	ranking    []RengokuScore
	rankingErr error
}

func (m *mockRengokuRepo) UpsertScore(_ uint32, _, _, _, _ uint32) error { return nil }
func (m *mockRengokuRepo) GetRanking(_ uint32, _ uint32) ([]RengokuScore, error) {
	return m.ranking, m.rankingErr
}

// --- mockDivaRepo ---

type mockDivaRepo struct {
	events    []DivaEvent
	eventsErr error

	// Point tracking for tests
	points   map[[2]uint32][2]int64 // [charID, eventID] -> [questPoints, bonusPoints]
	addErr   error
	getErr   error
	totalErr error
}

func (m *mockDivaRepo) DeleteEvents() error             { return nil }
func (m *mockDivaRepo) InsertEvent(_ uint32) error      { return nil }
func (m *mockDivaRepo) GetEvents() ([]DivaEvent, error) { return m.events, m.eventsErr }

func (m *mockDivaRepo) AddPoints(charID, eventID, questPoints, bonusPoints uint32) error {
	if m.addErr != nil {
		return m.addErr
	}
	if m.points == nil {
		m.points = make(map[[2]uint32][2]int64)
	}
	key := [2]uint32{charID, eventID}
	cur := m.points[key]
	cur[0] += int64(questPoints)
	cur[1] += int64(bonusPoints)
	m.points[key] = cur
	return nil
}

func (m *mockDivaRepo) GetPoints(charID, eventID uint32) (int64, int64, error) {
	if m.getErr != nil {
		return 0, 0, m.getErr
	}
	if m.points == nil {
		return 0, 0, nil
	}
	p := m.points[[2]uint32{charID, eventID}]
	return p[0], p[1], nil
}

func (m *mockDivaRepo) GetTotalPoints(eventID uint32) (int64, int64, error) {
	if m.totalErr != nil {
		return 0, 0, m.totalErr
	}
	var tq, tb int64
	for k, v := range m.points {
		if k[1] == eventID {
			tq += v[0]
			tb += v[1]
		}
	}
	return tq, tb, nil
}

func (m *mockDivaRepo) GetBeads() ([]int, error)                      { return nil, nil }
func (m *mockDivaRepo) AssignBead(_ uint32, _ int, _ time.Time) error { return nil }
func (m *mockDivaRepo) AddBeadPoints(_ uint32, _ int, _ int) error    { return nil }
func (m *mockDivaRepo) GetCharacterBeadPoints(_ uint32) (map[int]int, error) {
	return map[int]int{}, nil
}
func (m *mockDivaRepo) GetTotalBeadPoints() (int64, error)      { return 0, nil }
func (m *mockDivaRepo) GetTopBeadPerDay(_ int) (int, error)     { return 0, nil }
func (m *mockDivaRepo) CleanupBeads() error                     { return nil }
func (m *mockDivaRepo) GetPersonalPrizes() ([]DivaPrize, error) { return nil, nil }
func (m *mockDivaRepo) GetGuildPrizes() ([]DivaPrize, error)    { return nil, nil }
func (m *mockDivaRepo) GetCharacterInterceptionPoints(_ uint32) (map[string]int, error) {
	return map[string]int{}, nil
}
func (m *mockDivaRepo) AddInterceptionPoints(_ uint32, _ int, _ int) error { return nil }

// --- mockEventRepo ---

type mockEventRepo struct {
	feature       activeFeature
	featureErr    error
	loginBoosts   []loginBoost
	loginBoostErr error
	eventQuests   []EventQuest
	eventQuestErr error
}

func (m *mockEventRepo) GetFeatureWeapon(_ time.Time) (activeFeature, error) {
	return m.feature, m.featureErr
}
func (m *mockEventRepo) InsertFeatureWeapon(_ time.Time, _ uint32) error { return nil }
func (m *mockEventRepo) GetLoginBoosts(_ uint32) ([]loginBoost, error) {
	return m.loginBoosts, m.loginBoostErr
}
func (m *mockEventRepo) InsertLoginBoost(_ uint32, _ uint8, _, _ time.Time) error { return nil }
func (m *mockEventRepo) UpdateLoginBoost(_ uint32, _ uint8, _, _ time.Time) error { return nil }
func (m *mockEventRepo) GetEventQuests() ([]EventQuest, error) {
	return m.eventQuests, m.eventQuestErr
}
func (m *mockEventRepo) UpdateEventQuestStartTimes(_ []EventQuestUpdate) error { return nil }

// --- mockMiscRepo ---

type mockMiscRepo struct {
	trendWeapons    []uint16
	trendWeaponsErr error
}

func (m *mockMiscRepo) GetTrendWeapons(_ uint8) ([]uint16, error) {
	return m.trendWeapons, m.trendWeaponsErr
}
func (m *mockMiscRepo) UpsertTrendWeapon(_ uint16, _ uint8) error { return nil }

// --- mockMercenaryRepo ---

type mockMercenaryRepo struct {
	nextRastaID   uint32
	rastaIDErr    error
	nextAirouID   uint32
	airouIDErr    error
	loans         []MercenaryLoan
	loansErr      error
	catUsages     []GuildHuntCatUsage
	catUsagesErr  error
	guildAirou    [][]byte
	guildAirouErr error
}

func (m *mockMercenaryRepo) NextRastaID() (uint32, error) { return m.nextRastaID, m.rastaIDErr }
func (m *mockMercenaryRepo) NextAirouID() (uint32, error) { return m.nextAirouID, m.airouIDErr }
func (m *mockMercenaryRepo) GetMercenaryLoans(_ uint32) ([]MercenaryLoan, error) {
	return m.loans, m.loansErr
}
func (m *mockMercenaryRepo) GetGuildHuntCatsUsed(_ uint32) ([]GuildHuntCatUsage, error) {
	return m.catUsages, m.catUsagesErr
}
func (m *mockMercenaryRepo) GetGuildAirou(_ uint32) ([][]byte, error) {
	return m.guildAirou, m.guildAirouErr
}

// --- mockCafeRepo ---

type mockCafeRepo struct {
	bonuses       []CafeBonus
	bonusesErr    error
	claimable     []CafeBonus
	claimableErr  error
	bonusItemType uint32
	bonusItemQty  uint32
	bonusItemErr  error
}

func (m *mockCafeRepo) ResetAccepted(_ uint32) error             { return nil }
func (m *mockCafeRepo) GetBonuses(_ uint32) ([]CafeBonus, error) { return m.bonuses, m.bonusesErr }
func (m *mockCafeRepo) GetClaimable(_ uint32, _ int64) ([]CafeBonus, error) {
	return m.claimable, m.claimableErr
}
func (m *mockCafeRepo) GetBonusItem(_ uint32) (uint32, uint32, error) {
	return m.bonusItemType, m.bonusItemQty, m.bonusItemErr
}
func (m *mockCafeRepo) AcceptBonus(_, _ uint32) error { return nil }

// --- mockTournamentRepo ---

type mockTournamentRepo struct {
	active      *Tournament
	activeErr   error
	cups        []TournamentCup
	subEvents   []TournamentSubEvent
	ranks       []TournamentRankEntry
	registerID  uint32
	registerErr error
	entry       *TournamentEntry
	entryErr    error
}

func (m *mockTournamentRepo) GetActive(_ int64) (*Tournament, error) {
	return m.active, m.activeErr
}
func (m *mockTournamentRepo) GetCups(_ uint32) ([]TournamentCup, error) { return m.cups, nil }
func (m *mockTournamentRepo) GetSubEvents() ([]TournamentSubEvent, error) {
	return m.subEvents, nil
}
func (m *mockTournamentRepo) Register(_, _ uint32) (uint32, error) {
	return m.registerID, m.registerErr
}
func (m *mockTournamentRepo) GetEntry(_, _ uint32) (*TournamentEntry, error) {
	return m.entry, m.entryErr
}
func (m *mockTournamentRepo) SubmitResult(_, _, _, _, _ uint32) error { return nil }
func (m *mockTournamentRepo) GetLeaderboard(_ uint32) ([]TournamentRankEntry, error) {
	return m.ranks, nil
}
