package auditlog import ( "context" "math" "tm/pkg/audit" "tm/pkg/logger" "tm/pkg/response" ) // Service defines audit log query operations. type Service interface { Search(ctx context.Context, form SearchForm, pagination *response.Pagination) (*ListResponse, error) } type service struct { repository Repository logger logger.Logger } // NewService creates an audit log service. func NewService(repository Repository, log logger.Logger) Service { return &service{ repository: repository, logger: log, } } func (s *service) Search(ctx context.Context, form SearchForm, pagination *response.Pagination) (*ListResponse, error) { filter := audit.SearchFilter{ ActorID: form.ActorID, ActorType: form.ActorType, Action: form.Action, TargetType: form.TargetType, TargetID: form.TargetID, From: form.From, To: form.To, Limit: pagination.Limit, Offset: pagination.Offset, } result, err := s.repository.Search(ctx, filter) if err != nil { s.logger.Error("Failed to search audit logs", map[string]interface{}{ "error": err.Error(), }) return nil, err } entries := make([]*Entry, 0, len(result.Items)) for _, item := range result.Items { entries = append(entries, &Entry{ ActorID: item.ActorID, ActorType: item.ActorType, Action: item.Action, TargetType: item.TargetType, TargetID: item.TargetID, At: item.At, IP: item.IP, RequestID: item.RequestID, UserAgent: item.UserAgent, Success: item.Success, Metadata: item.Metadata, }) } total := result.TotalCount pages := 0 if pagination.Limit > 0 { pages = int(math.Ceil(float64(total) / float64(pagination.Limit))) } page := 1 if pagination.Limit > 0 { page = (pagination.Offset / pagination.Limit) + 1 } return &ListResponse{ Logs: entries, Meta: &ListMeta{ Total: total, Limit: pagination.Limit, Offset: pagination.Offset, Page: page, Pages: pages, }, }, nil }