package repository import ( "context" "database/sql" "fmt" "rag/file-system/internal/domain/model" ) type ShareRepoImpl struct { db *sql.DB } func NewShareRepository(db *sql.DB) *ShareRepoImpl { return &ShareRepoImpl{db: db} } func (r *ShareRepoImpl) Create(ctx context.Context, share *model.ShareLink) error { _, err := r.db.ExecContext(ctx, `INSERT INTO share_links (id, resource_type, resource_id, token, password, expires_at, download_count, max_downloads, created_by, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, share.ID, share.ResourceType, share.ResourceID, share.Token, share.Password, share.ExpiresAt, share.DownloadCount, share.MaxDownloads, share.CreatedBy, share.CreatedAt) if err != nil { return fmt.Errorf("failed to create share link: %w", err) } return nil } func (r *ShareRepoImpl) GetByToken(ctx context.Context, token string) (*model.ShareLink, error) { return r.queryOne(ctx, `SELECT id, resource_type, resource_id, token, password, expires_at, download_count, max_downloads, created_by, created_at FROM share_links WHERE token = $1`, token) } func (r *ShareRepoImpl) GetByID(ctx context.Context, id string) (*model.ShareLink, error) { return r.queryOne(ctx, `SELECT id, resource_type, resource_id, token, password, expires_at, download_count, max_downloads, created_by, created_at FROM share_links WHERE id = $1`, id) } func (r *ShareRepoImpl) Delete(ctx context.Context, id string, createdBy string) error { result, err := r.db.ExecContext(ctx, `DELETE FROM share_links WHERE id = $1 AND created_by = $2`, id, createdBy) if err != nil { return fmt.Errorf("failed to delete share link: %w", err) } rows, _ := result.RowsAffected() if rows == 0 { return fmt.Errorf("share link not found or not owned by user") } return nil } func (r *ShareRepoImpl) IncrementDownloadCount(ctx context.Context, token string) error { _, err := r.db.ExecContext(ctx, `UPDATE share_links SET download_count = download_count + 1 WHERE token = $1`, token) if err != nil { return fmt.Errorf("failed to increment download count: %w", err) } return nil } func (r *ShareRepoImpl) ListByResource(ctx context.Context, resourceType string, resourceID string) ([]model.ShareLink, error) { rows, err := r.db.QueryContext(ctx, `SELECT id, resource_type, resource_id, token, password, expires_at, download_count, max_downloads, created_by, created_at FROM share_links WHERE resource_type = $1 AND resource_id = $2 ORDER BY created_at DESC`, resourceType, resourceID) if err != nil { return nil, fmt.Errorf("failed to list share links: %w", err) } defer rows.Close() var links []model.ShareLink for rows.Next() { var s model.ShareLink if err := rows.Scan(&s.ID, &s.ResourceType, &s.ResourceID, &s.Token, &s.Password, &s.ExpiresAt, &s.DownloadCount, &s.MaxDownloads, &s.CreatedBy, &s.CreatedAt); err != nil { return nil, fmt.Errorf("failed to scan share link: %w", err) } links = append(links, s) } return links, rows.Err() } func (r *ShareRepoImpl) queryOne(ctx context.Context, query string, args ...interface{}) (*model.ShareLink, error) { var s model.ShareLink err := r.db.QueryRowContext(ctx, query, args...). Scan(&s.ID, &s.ResourceType, &s.ResourceID, &s.Token, &s.Password, &s.ExpiresAt, &s.DownloadCount, &s.MaxDownloads, &s.CreatedBy, &s.CreatedAt) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, fmt.Errorf("failed to query share link: %w", err) } return &s, nil }