package usecase import ( "context" "strings" "haixun-backend/internal/library/clock" app "haixun-backend/internal/library/errors" "haixun-backend/internal/library/errors/code" jobdom "haixun-backend/internal/model/job/domain/usecase" "haixun-backend/internal/model/publish_analytics/domain/entity" domrepo "haixun-backend/internal/model/publish_analytics/domain/repository" domusecase "haixun-backend/internal/model/publish_analytics/domain/usecase" "github.com/google/uuid" ) type publishAnalyticsUseCase struct { repo domrepo.Repository jobs jobdom.UseCase } func NewUseCase(repo domrepo.Repository, jobs jobdom.UseCase) domusecase.UseCase { return &publishAnalyticsUseCase{repo: repo, jobs: jobs} } func (u *publishAnalyticsUseCase) RecordCheckpoint(ctx context.Context, tenantID, ownerUID string, summary domusecase.PublishAnalyticsSummary) (*domusecase.PublishAnalyticsSummary, error) { tenantID = strings.TrimSpace(tenantID) ownerUID = strings.TrimSpace(ownerUID) if tenantID == "" || ownerUID == "" { return nil, app.For(code.AI).AuthUnauthorized("missing actor") } mediaID := strings.TrimSpace(summary.MediaID) if mediaID == "" { return nil, app.For(code.AI).InputMissingRequired("media_id is required") } checkpoint := strings.TrimSpace(summary.Checkpoint) if checkpoint == "" { return nil, app.For(code.AI).InputMissingRequired("checkpoint is required") } now := clock.NowUnixNano() analytics := &entity.PublishAnalytics{ ID: uuid.NewString(), TenantID: tenantID, OwnerUID: ownerUID, MediaID: mediaID, Permalink: strings.TrimSpace(summary.Permalink), PublishedAt: summary.PublishedAt, Checkpoint: checkpoint, LikeCount: summary.LikeCount, ReplyCount: summary.ReplyCount, RepostCount: summary.RepostCount, QuoteCount: summary.QuoteCount, ViewCount: summary.ViewCount, ShareCount: summary.ShareCount, ImpressionCount: summary.ImpressionCount, ReachCount: summary.ReachCount, CheckedAt: now, CreateAt: now, } created, err := u.repo.Upsert(ctx, analytics) if err != nil { return nil, err } out := toSummary(*created) return &out, nil } func (u *publishAnalyticsUseCase) ListByMedia(ctx context.Context, tenantID, ownerUID, mediaID string) ([]domusecase.PublishAnalyticsSummary, error) { tenantID = strings.TrimSpace(tenantID) ownerUID = strings.TrimSpace(ownerUID) mediaID = strings.TrimSpace(mediaID) if tenantID == "" || ownerUID == "" { return nil, app.For(code.AI).AuthUnauthorized("missing actor") } if mediaID == "" { return nil, app.For(code.AI).InputMissingRequired("media_id is required") } items, err := u.repo.ListByMedia(ctx, tenantID, ownerUID, mediaID) if err != nil { return nil, err } out := make([]domusecase.PublishAnalyticsSummary, 0, len(items)) for _, item := range items { out = append(out, toSummary(item)) } return out, nil } func toSummary(item entity.PublishAnalytics) domusecase.PublishAnalyticsSummary { return domusecase.PublishAnalyticsSummary{ ID: item.ID, MediaID: item.MediaID, Permalink: item.Permalink, PublishedAt: item.PublishedAt, Checkpoint: item.Checkpoint, LikeCount: item.LikeCount, ReplyCount: item.ReplyCount, RepostCount: item.RepostCount, QuoteCount: item.QuoteCount, ViewCount: item.ViewCount, ShareCount: item.ShareCount, ImpressionCount: item.ImpressionCount, ReachCount: item.ReachCount, CheckedAt: item.CheckedAt, CreateAt: item.CreateAt, } }