package usecase import ( "context" "strings" "haixun-backend/internal/model/content_matrix/domain/entity" domrepo "haixun-backend/internal/model/content_matrix/domain/repository" domusecase "haixun-backend/internal/model/content_matrix/domain/usecase" app "haixun-backend/internal/library/errors" "haixun-backend/internal/library/errors/code" libmongo "haixun-backend/internal/library/mongo" ) type contentMatrixUseCase struct { repo domrepo.Repository } func NewUseCase(repo domrepo.Repository) domusecase.UseCase { return &contentMatrixUseCase{repo: repo} } func (u *contentMatrixUseCase) Get(ctx context.Context, tenantID, ownerUID, brandID string) (*domusecase.MatrixSummary, error) { if err := requireActor(tenantID, ownerUID, brandID); err != nil { return nil, err } record, err := u.repo.GetByBrand(ctx, tenantID, ownerUID, brandID) if err != nil { return nil, err } if record == nil { return &domusecase.MatrixSummary{BrandID: brandID, Rows: []domusecase.Row{}}, nil } return toSummary(record), nil } func (u *contentMatrixUseCase) Upsert(ctx context.Context, req domusecase.UpsertRequest) (*domusecase.MatrixSummary, error) { if err := requireActor(req.TenantID, req.OwnerUID, req.BrandID); err != nil { return nil, err } rows := make([]entity.Row, 0, len(req.Rows)) for _, row := range req.Rows { rows = append(rows, entity.Row{ SortOrder: row.SortOrder, SearchTag: row.SearchTag, Angle: row.Angle, Hook: row.Hook, Text: row.Text, ReferenceNotes: row.ReferenceNotes, SourcePermalinks: row.SourcePermalinks, Rationale: row.Rationale, }) } record := &entity.ContentMatrix{ TenantID: req.TenantID, OwnerUID: req.OwnerUID, BrandID: req.BrandID, Rows: rows, GeneratedAt: req.GeneratedAt, } saved, err := u.repo.UpsertByBrand(ctx, record) if err != nil { return nil, err } return toSummary(saved), nil } func requireActor(tenantID, ownerUID, brandID string) error { if strings.TrimSpace(tenantID) == "" || strings.TrimSpace(ownerUID) == "" { return app.For(code.Brand).InputMissingRequired("tenant_id and uid are required") } if strings.TrimSpace(brandID) == "" { return app.For(code.Brand).InputMissingRequired("brand id is required") } return nil } func toSummary(record *entity.ContentMatrix) *domusecase.MatrixSummary { if record == nil { return nil } rows := make([]domusecase.Row, 0, len(record.Rows)) for _, row := range record.Rows { rows = append(rows, domusecase.Row{ SortOrder: row.SortOrder, SearchTag: row.SearchTag, Angle: row.Angle, Hook: row.Hook, Text: row.Text, ReferenceNotes: row.ReferenceNotes, SourcePermalinks: row.SourcePermalinks, Rationale: row.Rationale, }) } return &domusecase.MatrixSummary{ ID: record.ID, BrandID: libmongo.ResolveBrandID(record.BrandID, record.LegacyPersonaID), Rows: rows, GeneratedAt: record.GeneratedAt, CreateAt: record.CreateAt, UpdateAt: record.UpdateAt, } }