package usecase import ( "context" "errors" "math" "github.com/gofrs/uuid/v5" "github.com/saveinmed/backend-go/internal/domain" ) // RegisterCompany persists a new company and sets a new UUID. func (s *Service) RegisterCompany(ctx context.Context, company *domain.Company) error { company.ID = uuid.Must(uuid.NewV7()) return s.repo.CreateCompany(ctx, company) } // ListCompanies returns a paginated list of companies matching the filter. func (s *Service) ListCompanies(ctx context.Context, filter domain.CompanyFilter, page, pageSize int) (*domain.CompanyPage, error) { if pageSize <= 0 { pageSize = 20 } if page <= 0 { page = 1 } filter.Limit = pageSize filter.Offset = (page - 1) * pageSize companies, total, err := s.repo.ListCompanies(ctx, filter) if err != nil { return nil, err } return &domain.CompanyPage{Companies: companies, Total: total, Page: page, PageSize: pageSize}, nil } // GetCompany retrieves a company by ID. func (s *Service) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) { return s.repo.GetCompany(ctx, id) } // UpdateCompany persists changes to an existing company. func (s *Service) UpdateCompany(ctx context.Context, company *domain.Company) error { return s.repo.UpdateCompany(ctx, company) } // DeleteCompany removes a company by ID. func (s *Service) DeleteCompany(ctx context.Context, id uuid.UUID) error { return s.repo.DeleteCompany(ctx, id) } // VerifyCompany marks the company account as KYC-verified. func (s *Service) VerifyCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) { company, err := s.repo.GetCompany(ctx, id) if err != nil { return nil, err } company.IsVerified = true if err := s.repo.UpdateCompany(ctx, company); err != nil { return nil, err } return company, nil } // CalculateShippingOptions returns available delivery/pickup options for a vendor, // based on the buyer's location and cart total. func (s *Service) CalculateShippingOptions(ctx context.Context, vendorID uuid.UUID, buyerLat, buyerLng float64, cartTotalCents int64) ([]domain.ShippingOption, error) { company, err := s.repo.GetCompany(ctx, vendorID) if err != nil { return nil, err } if company == nil { return nil, errors.New("vendor not found") } settings, err := s.repo.GetShippingSettings(ctx, vendorID) if err != nil { return []domain.ShippingOption{}, nil } if settings == nil { return []domain.ShippingOption{}, nil } distance := domain.HaversineDistance(company.Latitude, company.Longitude, buyerLat, buyerLng) var options []domain.ShippingOption // Delivery option if settings.Active { if settings.MaxRadiusKm > 0 && distance <= settings.MaxRadiusKm { variableCost := int64(math.Round(distance * float64(settings.PricePerKmCents))) price := settings.MinFeeCents if variableCost > price { price = variableCost } if settings.FreeShippingThresholdCents != nil && *settings.FreeShippingThresholdCents > 0 && cartTotalCents >= *settings.FreeShippingThresholdCents { price = 0 } estMins := 30 + int(math.Round(distance*5)) options = append(options, domain.ShippingOption{ Type: domain.ShippingOptionTypeDelivery, ValueCents: price, EstimatedMinutes: estMins, Description: "Entrega PrĂ³pria", DistanceKm: distance, }) } } // Pickup option if settings.PickupActive { desc := "Retirada na loja" if settings.PickupAddress != "" { desc = "Retirada em: " + settings.PickupAddress } if settings.PickupHours != "" { desc += " (" + settings.PickupHours + ")" } options = append(options, domain.ShippingOption{ Type: domain.ShippingOptionTypePickup, ValueCents: 0, EstimatedMinutes: 60, Description: desc, DistanceKm: distance, }) } return options, nil }