package repository import ( "context" "fmt" "backend/pkg/library/cassandra" "backend/pkg/post/domain/entity" domainRepo "backend/pkg/post/domain/repository" "github.com/gocql/gocql" ) // LikeRepositoryParam 定義 LikeRepository 的初始化參數 type LikeRepositoryParam struct { DB *cassandra.DB Keyspace string } // LikeRepository 實作 domain repository 介面 type LikeRepository struct { repo cassandra.Repository[*entity.Like] db *cassandra.DB } // NewLikeRepository 創建新的 LikeRepository func NewLikeRepository(param LikeRepositoryParam) domainRepo.LikeRepository { repo, err := cassandra.NewRepository[*entity.Like](param.DB, param.Keyspace) if err != nil { panic(fmt.Sprintf("failed to create like repository: %v", err)) } return &LikeRepository{ repo: repo, db: param.DB, } } // Insert 插入單筆按讚 func (r *LikeRepository) Insert(ctx context.Context, data *entity.Like) error { if data == nil { return ErrInvalidInput } // 驗證資料 if err := data.Validate(); err != nil { return fmt.Errorf("%w: %v", ErrInvalidInput, err) } // 設置時間戳 data.SetTimestamps() // 如果是新按讚,生成 ID if data.IsNew() { data.ID = gocql.TimeUUID() } return r.repo.Insert(ctx, data) } // FindOne 根據 ID 查詢單筆按讚 func (r *LikeRepository) FindOne(ctx context.Context, id gocql.UUID) (*entity.Like, error) { var zeroUUID gocql.UUID if id == zeroUUID { return nil, ErrInvalidInput } like, err := r.repo.Get(ctx, id) if err != nil { if cassandra.IsNotFound(err) { return nil, ErrNotFound } return nil, fmt.Errorf("failed to find like: %w", err) } return like, nil } // Delete 刪除按讚 func (r *LikeRepository) Delete(ctx context.Context, id gocql.UUID) error { var zeroUUID gocql.UUID if id == zeroUUID { return ErrInvalidInput } return r.repo.Delete(ctx, id) } // FindByTargetID 根據目標 ID 查詢按讚列表 func (r *LikeRepository) FindByTargetID(ctx context.Context, targetID gocql.UUID, targetType string) ([]*entity.Like, error) { var zeroUUID gocql.UUID if targetID == zeroUUID { return nil, ErrInvalidInput } if targetType != "post" && targetType != "comment" { return nil, ErrInvalidInput } // 構建查詢 query := r.repo.Query(). Where(cassandra.Eq("target_id", targetID)). Where(cassandra.Eq("target_type", targetType)). OrderBy("created_at", cassandra.DESC) var likes []*entity.Like if err := query.Scan(ctx, &likes); err != nil { return nil, fmt.Errorf("failed to query likes: %w", err) } return likes, nil } // FindByUserUID 根據用戶 UID 查詢按讚列表 func (r *LikeRepository) FindByUserUID(ctx context.Context, userUID string, params *domainRepo.LikeQueryParams) ([]*entity.Like, int64, error) { if userUID == "" { return nil, 0, ErrInvalidInput } query := r.repo.Query().Where(cassandra.Eq("user_uid", userUID)) // 添加目標類型過濾 if params != nil && params.TargetType != nil { query = query.Where(cassandra.Eq("target_type", *params.TargetType)) } // 添加目標 ID 過濾 if params != nil && params.TargetID != nil { query = query.Where(cassandra.Eq("target_id", *params.TargetID)) } // 添加排序 orderBy := "created_at" if params != nil && params.OrderBy != "" { orderBy = params.OrderBy } order := cassandra.DESC if params != nil && params.OrderDirection == "ASC" { order = cassandra.ASC } query = query.OrderBy(orderBy, order) // 添加分頁 pageSize := int64(20) if params != nil && params.PageSize > 0 { pageSize = params.PageSize } query = query.Limit(int(pageSize)) var likes []*entity.Like if err := query.Scan(ctx, &likes); err != nil { return nil, 0, fmt.Errorf("failed to query likes: %w", err) } result := likes return result, int64(len(result)), nil } // FindByTargetAndUser 根據目標和用戶查詢按讚 func (r *LikeRepository) FindByTargetAndUser(ctx context.Context, targetID gocql.UUID, userUID string, targetType string) (*entity.Like, error) { var zeroUUID gocql.UUID if targetID == zeroUUID || userUID == "" { return nil, ErrInvalidInput } if targetType != "post" && targetType != "comment" { return nil, ErrInvalidInput } // 構建查詢 query := r.repo.Query(). Where(cassandra.Eq("target_id", targetID)). Where(cassandra.Eq("user_uid", userUID)). Where(cassandra.Eq("target_type", targetType)). Limit(1) var likes []*entity.Like if err := query.Scan(ctx, &likes); err != nil { if cassandra.IsNotFound(err) { return nil, ErrNotFound } return nil, fmt.Errorf("failed to query like: %w", err) } if len(likes) == 0 { return nil, ErrNotFound } return likes[0], nil } // CountByTargetID 計算目標的按讚數 func (r *LikeRepository) CountByTargetID(ctx context.Context, targetID gocql.UUID, targetType string) (int64, error) { var zeroUUID gocql.UUID if targetID == zeroUUID { return 0, ErrInvalidInput } if targetType != "post" && targetType != "comment" { return 0, ErrInvalidInput } // 構建查詢 query := r.repo.Query(). Where(cassandra.Eq("target_id", targetID)). Where(cassandra.Eq("target_type", targetType)) count, err := query.Count(ctx) if err != nil { return 0, fmt.Errorf("failed to count likes: %w", err) } return count, nil } // DeleteByTargetAndUser 根據目標和用戶刪除按讚 func (r *LikeRepository) DeleteByTargetAndUser(ctx context.Context, targetID gocql.UUID, userUID string, targetType string) error { // 先查詢按讚 like, err := r.FindByTargetAndUser(ctx, targetID, userUID, targetType) if err != nil { return err } // 刪除按讚 return r.Delete(ctx, like.ID) }