package repositories import ( "context" "fmt" "github.com/CubeCraft-Creations/Extrudex/backend/internal/models" "github.com/jackc/pgx/v5/pgxpool" ) // UsageLogRepository handles database queries for usage_logs. type UsageLogRepository struct { pool *pgxpool.Pool } // NewUsageLogRepository creates a UsageLogRepository backed by the given pool. func NewUsageLogRepository(pool *pgxpool.Pool) *UsageLogRepository { return &UsageLogRepository{pool: pool} } // UsageLogFilter holds query parameters for listing usage logs. type UsageLogFilter struct { SpoolID *int // filter by filament_spool_id JobID *int // filter by print_job_id Limit int Offset int } // GetAll returns usage logs matching the given filters, with pagination. func (r *UsageLogRepository) GetAll(ctx context.Context, filter UsageLogFilter) ([]models.UsageLog, int, error) { conditions := []string{"1=1"} args := []interface{}{} argIdx := 1 if filter.SpoolID != nil { conditions = append(conditions, fmt.Sprintf("ul.filament_spool_id = $%d", argIdx)) args = append(args, *filter.SpoolID) argIdx++ } if filter.JobID != nil { conditions = append(conditions, fmt.Sprintf("ul.print_job_id = $%d", argIdx)) args = append(args, *filter.JobID) argIdx++ } whereClause := "WHERE " + fmt.Sprintf("%s", conditions[0]) for _, c := range conditions[1:] { whereClause += " AND " + c } // Count. var total int countQuery := "SELECT COUNT(*) FROM usage_logs ul " + whereClause if err := r.pool.QueryRow(ctx, countQuery, args...).Scan(&total); err != nil { return nil, 0, err } // Query with pagination. dataQuery := `SELECT id, print_job_id, filament_spool_id, mm_extruded, grams_used, cost_usd, logged_at, created_at FROM usage_logs ul ` + whereClause + " ORDER BY ul.logged_at DESC" + fmt.Sprintf(" LIMIT $%d OFFSET $%d", argIdx, argIdx+1) dataArgs := make([]interface{}, len(args)) copy(dataArgs, args) dataArgs = append(dataArgs, filter.Limit, filter.Offset) rows, err := r.pool.Query(ctx, dataQuery, dataArgs...) if err != nil { return nil, 0, err } defer rows.Close() var logs []models.UsageLog for rows.Next() { var l models.UsageLog if err := rows.Scan( &l.ID, &l.PrintJobID, &l.FilamentSpoolID, &l.MMExtruded, &l.GramsUsed, &l.CostUSD, &l.LoggedAt, &l.CreatedAt, ); err != nil { return nil, 0, err } logs = append(logs, l) } if err := rows.Err(); err != nil { return nil, 0, err } if logs == nil { logs = []models.UsageLog{} } return logs, total, nil }