package repository import ( "context" "sync" "apps/backend/internal/module/threads/domain" ) // MemoryStore for unit tests. type MemoryStore struct { mu sync.Mutex byID map[string]*domain.Account state map[string]*domain.OAuthState } func NewMemory() *MemoryStore { return &MemoryStore{ byID: map[string]*domain.Account{}, state: map[string]*domain.OAuthState{}, } } func (s *MemoryStore) Insert(_ context.Context, a *domain.Account) error { s.mu.Lock() defer s.mu.Unlock() cp := *a s.byID[a.ID] = &cp return nil } func (s *MemoryStore) Update(_ context.Context, a *domain.Account) error { s.mu.Lock() defer s.mu.Unlock() if _, ok := s.byID[a.ID]; !ok { return domain.ErrNotFound } cp := *a s.byID[a.ID] = &cp return nil } func (s *MemoryStore) FindByID(_ context.Context, id string) (*domain.Account, error) { s.mu.Lock() defer s.mu.Unlock() a, ok := s.byID[id] if !ok { return nil, domain.ErrNotFound } cp := *a return &cp, nil } func (s *MemoryStore) FindByOwnerAndThreadsUser(_ context.Context, ownerUID int64, threadsUserID string) (*domain.Account, error) { s.mu.Lock() defer s.mu.Unlock() if threadsUserID == "" { return nil, domain.ErrNotFound } for _, a := range s.byID { if a.OwnerUID == ownerUID && a.ThreadsUserID == threadsUserID { cp := *a return &cp, nil } } return nil, domain.ErrNotFound } func (s *MemoryStore) ListByOwner(_ context.Context, ownerUID int64) ([]*domain.Account, error) { s.mu.Lock() defer s.mu.Unlock() var out []*domain.Account for _, a := range s.byID { if a.OwnerUID == ownerUID { cp := *a out = append(out, &cp) } } return out, nil } func (s *MemoryStore) Delete(_ context.Context, id string) error { s.mu.Lock() defer s.mu.Unlock() if _, ok := s.byID[id]; !ok { return domain.ErrNotFound } delete(s.byID, id) return nil } func (s *MemoryStore) SaveState(_ context.Context, st *domain.OAuthState) error { s.mu.Lock() defer s.mu.Unlock() cp := *st s.state[st.State] = &cp return nil } func (s *MemoryStore) TakeState(_ context.Context, state string) (*domain.OAuthState, error) { s.mu.Lock() defer s.mu.Unlock() st, ok := s.state[state] if !ok { return nil, domain.ErrInvalidState } delete(s.state, state) if st.ExpiresAt > 0 && domain.NowNano() > st.ExpiresAt { return nil, domain.ErrInvalidState } cp := *st return &cp, nil } var _ domain.Repository = (*MemoryStore)(nil)