package usecase import ( "context" "golang.org/x/crypto/bcrypt" "github.com/gofrs/uuid/v5" "github.com/saveinmed/backend-go/internal/domain" ) // Repository defines DB contract for the core entities. type Repository interface { CreateCompany(ctx context.Context, company *domain.Company) error ListCompanies(ctx context.Context) ([]domain.Company, error) CreateProduct(ctx context.Context, product *domain.Product) error ListProducts(ctx context.Context) ([]domain.Product, error) CreateOrder(ctx context.Context, order *domain.Order) error GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) UpdateOrderStatus(ctx context.Context, id uuid.UUID, status domain.OrderStatus) error CreateUser(ctx context.Context, user *domain.User) error ListUsers(ctx context.Context, filter domain.UserFilter) ([]domain.User, int64, error) GetUser(ctx context.Context, id uuid.UUID) (*domain.User, error) UpdateUser(ctx context.Context, user *domain.User) error DeleteUser(ctx context.Context, id uuid.UUID) error } // PaymentGateway abstracts Mercado Pago integration. type PaymentGateway interface { CreatePreference(ctx context.Context, order *domain.Order) (*domain.PaymentPreference, error) } type Service struct { repo Repository pay PaymentGateway } // NewService wires use cases together. func NewService(repo Repository, pay PaymentGateway) *Service { return &Service{repo: repo, pay: pay} } func (s *Service) RegisterCompany(ctx context.Context, company *domain.Company) error { company.ID = uuid.Must(uuid.NewV7()) return s.repo.CreateCompany(ctx, company) } func (s *Service) ListCompanies(ctx context.Context) ([]domain.Company, error) { return s.repo.ListCompanies(ctx) } func (s *Service) RegisterProduct(ctx context.Context, product *domain.Product) error { product.ID = uuid.Must(uuid.NewV7()) return s.repo.CreateProduct(ctx, product) } func (s *Service) ListProducts(ctx context.Context) ([]domain.Product, error) { return s.repo.ListProducts(ctx) } func (s *Service) CreateOrder(ctx context.Context, order *domain.Order) error { order.ID = uuid.Must(uuid.NewV7()) order.Status = domain.OrderStatusPending return s.repo.CreateOrder(ctx, order) } func (s *Service) GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) { return s.repo.GetOrder(ctx, id) } func (s *Service) UpdateOrderStatus(ctx context.Context, id uuid.UUID, status domain.OrderStatus) error { return s.repo.UpdateOrderStatus(ctx, id, status) } func (s *Service) CreatePaymentPreference(ctx context.Context, id uuid.UUID) (*domain.PaymentPreference, error) { order, err := s.repo.GetOrder(ctx, id) if err != nil { return nil, err } return s.pay.CreatePreference(ctx, order) } func (s *Service) CreateUser(ctx context.Context, user *domain.User, password string) error { hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } user.ID = uuid.Must(uuid.NewV7()) user.PasswordHash = string(hashed) return s.repo.CreateUser(ctx, user) } func (s *Service) ListUsers(ctx context.Context, filter domain.UserFilter, page, pageSize int) (*domain.UserPage, error) { if page < 1 { page = 1 } if pageSize <= 0 { pageSize = 20 } filter.Limit = pageSize filter.Offset = (page - 1) * pageSize users, total, err := s.repo.ListUsers(ctx, filter) if err != nil { return nil, err } return &domain.UserPage{Users: users, Total: total, Page: page, PageSize: pageSize}, nil } func (s *Service) GetUser(ctx context.Context, id uuid.UUID) (*domain.User, error) { return s.repo.GetUser(ctx, id) } func (s *Service) UpdateUser(ctx context.Context, user *domain.User, newPassword string) error { if newPassword != "" { hashed, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost) if err != nil { return err } user.PasswordHash = string(hashed) } return s.repo.UpdateUser(ctx, user) } func (s *Service) DeleteUser(ctx context.Context, id uuid.UUID) error { return s.repo.DeleteUser(ctx, id) }