package httpapi

import (
	"net/http"

	"git.azzamo.net/Michilis/Spanglish/photo-api/internal/store"
)

// listPublicGalleries is the public index: only visibility='public'
// galleries ever appear here.
func (s *Server) listPublicGalleries(w http.ResponseWriter, r *http.Request) {
	galleries, err := s.db.ListPublicGalleries(r.Context())
	if err != nil {
		writeStoreError(w, err, "")
		return
	}
	out := make([]galleryJSON, 0, len(galleries))
	for _, g := range galleries {
		out = append(out, s.galleryToJSON(r.Context(), g, "", false))
	}
	writeJSON(w, http.StatusOK, map[string]any{"galleries": out})
}

// getPublicGallery serves a single gallery to any authorized viewer.
// ?token= carries the share token for link/ticket modes.
func (s *Server) getPublicGallery(w http.ResponseWriter, r *http.Request) {
	g, err := s.db.GetGalleryBySlug(r.Context(), r.PathValue("slug"))
	if err != nil {
		writeStoreError(w, err, "Gallery not found")
		return
	}
	s.respondGalleryView(w, r, g)
}

// getEventGallery serves the newest gallery linked to an event, backing the
// /events/{slug}/gallery public page. Same access rules as by-slug.
func (s *Server) getEventGallery(w http.ResponseWriter, r *http.Request) {
	ev, err := s.db.GetEventSummaryBySlug(r.Context(), r.PathValue("eventSlug"))
	if err != nil {
		writeStoreError(w, err, "Gallery not found")
		return
	}
	g, err := s.db.GetGalleryByEventID(r.Context(), ev.ID)
	if err != nil {
		writeStoreError(w, err, "Gallery not found")
		return
	}
	s.respondGalleryView(w, r, g)
}

func (s *Server) respondGalleryView(w http.ResponseWriter, r *http.Request, g store.Gallery) {
	user := s.optionalUser(r)
	token := r.URL.Query().Get("token")
	if denial := s.authorize(r, g, user, token); denial != nil {
		writeError(w, denial.status, denial.msg)
		return
	}

	// Non-public galleries get a short-lived view token on every file URL,
	// because the browser's <img> requests cannot carry the Bearer header
	// that authorized this gallery fetch. Public galleries need none.
	urlToken := s.viewTokenFor(g)

	photos, err := s.db.ListPhotos(r.Context(), g.ID, true)
	if err != nil {
		writeStoreError(w, err, "")
		return
	}
	s.fillPreviewSizes(r.Context(), photos)
	out := make([]photoJSON, 0, len(photos))
	for _, p := range photos {
		out = append(out, s.photoToJSON(p, urlToken, false))
	}
	writeJSON(w, http.StatusOK, map[string]any{
		"gallery": s.galleryToJSON(r.Context(), g, urlToken, false),
		"photos":  out,
	})
}
