package contacts import ( "context" "strings" "github.com/ultisuite/ulti-backend/internal/api/paginate" "github.com/ultisuite/ulti-backend/internal/api/query" "github.com/ultisuite/ulti-backend/internal/nextcloud" ) type Service struct { nc *nextcloud.Client } func NewService(nc *nextcloud.Client) *Service { return &Service{nc: nc} } func bookPath(userID, bookID string) string { return "/remote.php/dav/addressbooks/users/" + userID + "/" + bookID + "/" } func (s *Service) ListAddressBooks(ctx context.Context, userID string) ([]nextcloud.AddressBook, error) { return s.nc.ListAddressBooks(ctx, userID) } type ContactsList struct { Contacts []nextcloud.Contact `json:"contacts"` Pagination query.PaginationMeta `json:"pagination,omitempty"` } func (s *Service) ListContacts(ctx context.Context, userID, bookID string, params query.ListParams) (ContactsList, error) { contacts, err := s.nc.ListContacts(ctx, userID, bookPath(userID, bookID)) if err != nil { return ContactsList{}, err } filtered := filterContacts(contacts, params.Q) page, total := paginate.Slice(filtered, params.Offset(), params.Limit()) return ContactsList{ Contacts: page, Pagination: params.Meta(&total), }, nil } func (s *Service) SearchContacts(ctx context.Context, userID, bookID, q string, params query.ListParams) (ContactsList, error) { searchQ := strings.TrimSpace(q) if searchQ == "" { searchQ = strings.TrimSpace(params.Q) } contacts, err := s.nc.SearchContacts(ctx, userID, bookPath(userID, bookID), searchQ) if err != nil { return ContactsList{}, err } page, total := paginate.Slice(contacts, params.Offset(), params.Limit()) return ContactsList{ Contacts: page, Pagination: params.Meta(&total), }, nil } func (s *Service) CreateContact(ctx context.Context, userID, bookID string, contact *nextcloud.Contact) error { return s.nc.CreateContact(ctx, userID, bookPath(userID, bookID), contact) } func (s *Service) DeleteContact(ctx context.Context, userID, contactPath string) error { return s.nc.DeleteContact(ctx, userID, contactPath) } func filterContacts(contacts []nextcloud.Contact, q string) []nextcloud.Contact { q = strings.ToLower(strings.TrimSpace(q)) if q == "" { return contacts } out := make([]nextcloud.Contact, 0, len(contacts)) for _, c := range contacts { if strings.Contains(strings.ToLower(c.FullName), q) || strings.Contains(strings.ToLower(c.Email), q) || strings.Contains(strings.ToLower(c.Phone), q) || strings.Contains(strings.ToLower(c.Org), q) { out = append(out, c) } } return out }