package api

import (
	"net/http"
	"strconv"

	"github.com/jackc/pgx/v5/pgtype"

	"git.fabledsword.com/bvandeusen/minstrel/internal/auth"
	"git.fabledsword.com/bvandeusen/minstrel/internal/recommendation"
)

// suggestionView is the wire shape returned by GET /api/discover/suggestions.
type suggestionView struct {
	MBID        string                 `json:"mbid"`
	Name        string                 `json:"name"`
	Score       float64                `json:"score"`
	Attribution []seedContributionView `json:"attribution"`
}

type seedContributionView struct {
	ArtistID     pgtype.UUID `json:"artist_id"`
	Name         string      `json:"name"`
	Contribution float64     `json:"contribution"`
	IsLiked      bool        `json:"is_liked"`
	PlayCount    int64       `json:"play_count"`
}

// handleListSuggestions implements GET /api/discover/suggestions.
//
// Query params:
//   - limit (default 12, capped at 50)
//   - half_life_days (default 30)
//
// Returns 200 with a JSON array (possibly empty). Read-only; no admin gate.
func (h *handlers) handleListSuggestions(w http.ResponseWriter, r *http.Request) {
	user, ok := auth.UserFromContext(r.Context())
	if !ok {
		writeErr(w, http.StatusUnauthorized, "unauthorized", "authentication required")
		return
	}
	limit := 12
	if v := r.URL.Query().Get("limit"); v != "" {
		n, err := strconv.Atoi(v)
		if err != nil || n < 1 {
			writeErr(w, http.StatusBadRequest, "bad_request", "invalid limit")
			return
		}
		limit = n
	}
	halfLife := 30.0
	if v := r.URL.Query().Get("half_life_days"); v != "" {
		f, err := strconv.ParseFloat(v, 64)
		if err != nil || f <= 0 {
			writeErr(w, http.StatusBadRequest, "bad_request", "invalid half_life_days")
			return
		}
		halfLife = f
	}

	suggestions, err := recommendation.SuggestArtists(r.Context(), h.pool, user.ID, halfLife, limit)
	if err != nil {
		h.logger.Error("api: list suggestions", "err", err)
		writeErr(w, http.StatusInternalServerError, "server_error", "failed to load suggestions")
		return
	}

	out := make([]suggestionView, 0, len(suggestions))
	for _, s := range suggestions {
		attr := make([]seedContributionView, 0, len(s.Attribution))
		for _, a := range s.Attribution {
			attr = append(attr, seedContributionView{
				ArtistID:     a.ArtistID,
				Name:         a.Name,
				Contribution: a.Contribution,
				IsLiked:      a.IsLiked,
				PlayCount:    a.PlayCount,
			})
		}
		out = append(out, suggestionView{
			MBID: s.MBID, Name: s.Name, Score: s.Score, Attribution: attr,
		})
	}
	writeJSON(w, http.StatusOK, out)
}
