package storage import ( "fmt" "strings" "sync" "git.coopgo.io/coopgo-platform/solidarity-transport/types" "github.com/google/uuid" "github.com/spf13/viper" ) // MockStorage implements the Storage interface for testing purposes type MockStorage struct { config *viper.Viper mu sync.RWMutex availabilities map[string]*types.DriverRegularAvailability journeys map[string]*types.DriverJourney bookings map[string]*types.Booking availabilitiesByDriver map[string][]*types.DriverRegularAvailability } // NewMockStorage creates a new mock storage instance func NewMockStorage(cfg *viper.Viper) Storage { return &MockStorage{ config: cfg, availabilities: make(map[string]*types.DriverRegularAvailability), journeys: make(map[string]*types.DriverJourney), bookings: make(map[string]*types.Booking), availabilitiesByDriver: make(map[string][]*types.DriverRegularAvailability), } } // Driver Regular Availability methods func (m *MockStorage) CreateDriverRegularAvailability(availability types.DriverRegularAvailability) error { m.mu.Lock() defer m.mu.Unlock() if availability.ID == "" { availability.ID = uuid.New().String() } m.availabilities[availability.ID] = &availability // Update driver index m.availabilitiesByDriver[availability.DriverId] = append( m.availabilitiesByDriver[availability.DriverId], &availability, ) return nil } func (m *MockStorage) CreateDriverRegularAvailabilities(availabilities []*types.DriverRegularAvailability) error { for _, availability := range availabilities { if err := m.CreateDriverRegularAvailability(*availability); err != nil { return err } } return nil } func (m *MockStorage) DeleteDriverRegularAvailability(driverid string, availabilityid string) error { m.mu.Lock() defer m.mu.Unlock() availability, exists := m.availabilities[availabilityid] if !exists { return fmt.Errorf("availability %s not found", availabilityid) } if availability.DriverId != driverid { return fmt.Errorf("availability %s does not belong to driver %s", availabilityid, driverid) } delete(m.availabilities, availabilityid) // Update driver index driverAvailabilities := m.availabilitiesByDriver[driverid] for i, a := range driverAvailabilities { if a.ID == availabilityid { m.availabilitiesByDriver[driverid] = append(driverAvailabilities[:i], driverAvailabilities[i+1:]...) break } } return nil } func (m *MockStorage) GetDriverRegularAvailability(driverid string, availabilityid string) (*types.DriverRegularAvailability, error) { m.mu.RLock() defer m.mu.RUnlock() availability, exists := m.availabilities[availabilityid] if !exists { return nil, fmt.Errorf("availability %s not found", availabilityid) } if availability.DriverId != driverid { return nil, fmt.Errorf("availability %s does not belong to driver %s", availabilityid, driverid) } return availability, nil } func (m *MockStorage) GetDriverRegularAvailabilities(driverid string) ([]*types.DriverRegularAvailability, error) { m.mu.RLock() defer m.mu.RUnlock() return m.availabilitiesByDriver[driverid], nil } func (m *MockStorage) GetRegularAvailabilities(day int, timeInDay string) ([]*types.DriverRegularAvailability, error) { m.mu.RLock() defer m.mu.RUnlock() var result []*types.DriverRegularAvailability for _, availability := range m.availabilities { // Match day if availability.Day != day { continue } // For testing, just return all availabilities for the day // Let the handler do the time filtering logic result = append(result, availability) } return result, nil } // timeMatches is a simple time matching function for testing func (m *MockStorage) timeMatches(availabilityTime, requestedTime string) bool { // Simple string matching for testing - real implementation would parse times return strings.HasPrefix(availabilityTime, requestedTime[:2]) // Match hour } // Driver Journey methods func (m *MockStorage) PushDriverJourneys(journeys []*types.DriverJourney) error { m.mu.Lock() defer m.mu.Unlock() for _, journey := range journeys { if journey.Id == "" { journey.Id = uuid.New().String() } m.journeys[journey.Id] = journey } return nil } func (m *MockStorage) GetDriverJourney(id string) (*types.DriverJourney, error) { m.mu.RLock() defer m.mu.RUnlock() journey, exists := m.journeys[id] if !exists { return nil, fmt.Errorf("journey %s not found", id) } return journey, nil } func (m *MockStorage) UpdateDriverJourney(journey types.DriverJourney) error { m.mu.Lock() defer m.mu.Unlock() if _, exists := m.journeys[journey.Id]; !exists { return fmt.Errorf("journey %s not found", journey.Id) } m.journeys[journey.Id] = &journey return nil } // Booking methods func (m *MockStorage) CreateBooking(booking types.Booking) error { m.mu.Lock() defer m.mu.Unlock() if booking.Id == "" { booking.Id = uuid.New().String() } m.bookings[booking.Id] = &booking return nil } func (m *MockStorage) GetAllBookings() ([]*types.Booking, error) { m.mu.RLock() defer m.mu.RUnlock() var result []*types.Booking for _, booking := range m.bookings { result = append(result, booking) } return result, nil } func (m *MockStorage) GetBooking(id string) (*types.Booking, error) { m.mu.RLock() defer m.mu.RUnlock() booking, exists := m.bookings[id] if !exists { return nil, fmt.Errorf("booking %s not found", id) } return booking, nil } func (m *MockStorage) UpdateBooking(booking types.Booking) error { m.mu.Lock() defer m.mu.Unlock() if _, exists := m.bookings[booking.Id]; !exists { return fmt.Errorf("booking %s not found", booking.Id) } m.bookings[booking.Id] = &booking return nil } func (m *MockStorage) UpdateBookingStatus(bookingid string, newStatus string, reason string) error { m.mu.Lock() defer m.mu.Unlock() booking, exists := m.bookings[bookingid] if !exists { return fmt.Errorf("booking %s not found", bookingid) } booking.Status = newStatus // In a real implementation, we might store the reason in a separate field return nil } // Helper methods for testing // Reset clears all data - useful for test setup func (m *MockStorage) Reset() { m.mu.Lock() defer m.mu.Unlock() m.availabilities = make(map[string]*types.DriverRegularAvailability) m.journeys = make(map[string]*types.DriverJourney) m.bookings = make(map[string]*types.Booking) m.availabilitiesByDriver = make(map[string][]*types.DriverRegularAvailability) } // GetAllJourneys returns all stored journeys - useful for testing func (m *MockStorage) GetAllJourneys() []*types.DriverJourney { m.mu.RLock() defer m.mu.RUnlock() var result []*types.DriverJourney for _, journey := range m.journeys { result = append(result, journey) } return result } // GetAllAvailabilities returns all stored availabilities - useful for testing func (m *MockStorage) GetAllAvailabilities() []*types.DriverRegularAvailability { m.mu.RLock() defer m.mu.RUnlock() var result []*types.DriverRegularAvailability for _, availability := range m.availabilities { result = append(result, availability) } return result }