package repository import ( "context" "fmt" "time" "github.com/prabhupadasays/spsays-bff/internal/model" ) // ListShortURLs returns a page of shortened URLs filtered by an optional query // (matched against code or target URL), newest first, with the total count. func (r *AdminRepo) ListShortURLs(ctx context.Context, q string, limit, offset int) ([]model.AdminShortURL, int, error) { limit = clampLimit(limit) rows, err := r.pg.Pool.Query(ctx, ` SELECT id, code, long_url, content_type, click_count, human_click_count, disabled, created_at, COUNT(*) OVER() AS total FROM shortened_urls WHERE ($1 = '' OR code ILIKE '%'||$1||'%' OR long_url ILIKE '%'||$1||'%') ORDER BY created_at DESC LIMIT $2 OFFSET $3`, q, limit, offset) if err != nil { return nil, 0, fmt.Errorf("admin list short urls: %w", err) } defer rows.Close() out := []model.AdminShortURL{} total := 0 for rows.Next() { var s model.AdminShortURL if err := rows.Scan(&s.ID, &s.Code, &s.LongURL, &s.ContentType, &s.ClickCount, &s.HumanClickCount, &s.Disabled, &s.CreatedAt, &total); err != nil { return nil, 0, fmt.Errorf("scan admin short url: %w", err) } out = append(out, s) } return out, total, rows.Err() } // ShortURLStats computes created + click counts for the three fixed windows // (thresholds passed in), the all-time totals, and — when from/to is given — // a custom range (from inclusive, to exclusive). "Created" comes from // shortened_urls.created_at; "clicks" from the shortened_url_clicks log. func (r *AdminRepo) ShortURLStats( ctx context.Context, todayStart, weekStart, monthStart time.Time, from, to *time.Time, ) (*model.ShortURLStats, error) { var s model.ShortURLStats if err := r.pg.Pool.QueryRow(ctx, ` SELECT COUNT(*), COUNT(*) FILTER (WHERE created_at >= $1), COUNT(*) FILTER (WHERE created_at >= $2), COUNT(*) FILTER (WHERE created_at >= $3) FROM shortened_urls`, todayStart, weekStart, monthStart). Scan(&s.TotalURLs, &s.Today.Created, &s.Week.Created, &s.Month.Created); err != nil { return nil, fmt.Errorf("short url created stats: %w", err) } if err := r.pg.Pool.QueryRow(ctx, ` SELECT COUNT(*), COUNT(*) FILTER (WHERE clicked_at >= $1), COUNT(*) FILTER (WHERE clicked_at >= $2), COUNT(*) FILTER (WHERE clicked_at >= $3) FROM shortened_url_clicks`, todayStart, weekStart, monthStart). Scan(&s.TotalClicks, &s.Today.Clicks, &s.Week.Clicks, &s.Month.Clicks); err != nil { return nil, fmt.Errorf("short url click stats: %w", err) } if from != nil && to != nil { var rng model.ShortURLRangeStat if err := r.pg.Pool.QueryRow(ctx, `SELECT COUNT(*) FROM shortened_urls WHERE created_at >= $1 AND created_at < $2`, *from, *to).Scan(&rng.Created); err != nil { return nil, fmt.Errorf("short url range created: %w", err) } if err := r.pg.Pool.QueryRow(ctx, `SELECT COUNT(*) FROM shortened_url_clicks WHERE clicked_at >= $1 AND clicked_at < $2`, *from, *to).Scan(&rng.Clicks); err != nil { return nil, fmt.Errorf("short url range clicks: %w", err) } s.Range = &rng } return &s, nil }