package repository import ( "context" "gorm.io/gorm" "gorm.io/gorm/clause" "with_you/internal/model" ) type PostRefRepository interface { BatchUpsert(ctx context.Context, sourcePostID string, targetPostIDs []string) error DeleteBySourcePostID(ctx context.Context, sourcePostID string) error GetSourcesByTargetPostID(ctx context.Context, targetPostID string, page, pageSize int) ([]model.PostReference, int64, error) GetTargetsBySourcePostID(ctx context.Context, sourcePostID string) ([]model.PostReference, error) MarkStatusByTargetPostID(ctx context.Context, targetPostID string, status model.PostReferenceStatus) error IncrementClickCount(ctx context.Context, sourcePostID, targetPostID string) error } type postRefRepository struct { db *gorm.DB } func NewPostRefRepository(db *gorm.DB) PostRefRepository { return &postRefRepository{db: db} } func (r *postRefRepository) BatchUpsert(ctx context.Context, sourcePostID string, targetPostIDs []string) error { if len(targetPostIDs) == 0 { return nil } refs := make([]model.PostReference, 0, len(targetPostIDs)) for _, targetID := range targetPostIDs { refs = append(refs, model.PostReference{ SourcePostID: sourcePostID, TargetPostID: targetID, Status: model.PostRefActive, }) } return r.db.WithContext(ctx).Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "source_post_id"}, {Name: "target_post_id"}}, DoUpdates: clause.AssignmentColumns([]string{"status", "updated_at"}), }).Create(&refs).Error } func (r *postRefRepository) DeleteBySourcePostID(ctx context.Context, sourcePostID string) error { return r.db.WithContext(ctx).Where("source_post_id = ?", sourcePostID).Delete(&model.PostReference{}).Error } func (r *postRefRepository) GetSourcesByTargetPostID(ctx context.Context, targetPostID string, page, pageSize int) ([]model.PostReference, int64, error) { var refs []model.PostReference var total int64 if err := r.db.WithContext(ctx).Model(&model.PostReference{}). Where("target_post_id = ? AND status = ?", targetPostID, model.PostRefActive). Count(&total).Error; err != nil { return nil, 0, err } offset := (page - 1) * pageSize if err := r.db.WithContext(ctx). Where("target_post_id = ? AND status = ?", targetPostID, model.PostRefActive). Preload("SourcePost"). Preload("SourcePost.User"). Order("created_at DESC"). Offset(offset).Limit(pageSize). Find(&refs).Error; err != nil { return nil, 0, err } return refs, total, nil } func (r *postRefRepository) GetTargetsBySourcePostID(ctx context.Context, sourcePostID string) ([]model.PostReference, error) { var refs []model.PostReference if err := r.db.WithContext(ctx). Where("source_post_id = ?", sourcePostID). Preload("TargetPost"). Preload("TargetPost.User"). Find(&refs).Error; err != nil { return nil, err } return refs, nil } func (r *postRefRepository) MarkStatusByTargetPostID(ctx context.Context, targetPostID string, status model.PostReferenceStatus) error { return r.db.WithContext(ctx).Model(&model.PostReference{}). Where("target_post_id = ?", targetPostID). Update("status", status).Error } func (r *postRefRepository) IncrementClickCount(ctx context.Context, sourcePostID, targetPostID string) error { return r.db.WithContext(ctx).Model(&model.PostReference{}). Where("source_post_id = ? AND target_post_id = ?", sourcePostID, targetPostID). UpdateColumn("click_count", gorm.Expr("click_count + 1")).Error }