package api

import (
	"encoding/json"
	"net/http"
	"net/url"

	"github.com/ponzischeme89/memby/server/internal/cache"
	"github.com/ponzischeme89/memby/server/internal/store"
)

type personFilmographyResponse struct {
	Items []json.RawMessage `json:"items"`
}

// handlePerson returns Emby's person item. PremiereDate and EndDate are the person's
// birth and death dates; Overview is their biography.
func (s *Server) handlePerson(w http.ResponseWriter, r *http.Request, sess store.Session) {
	ctx := r.Context()
	personID := r.PathValue("id")
	if personID == "" {
		writeError(w, http.StatusBadRequest, "person id is required")
		return
	}
	key := cache.UserKey(sess.EmbyUserID, "person:v1:"+personID)
	if raw, err := s.cache.Get(ctx, key); err == nil {
		w.Header().Set("X-Memby-Cache", "hit")
		writeRaw(w, http.StatusOK, raw)
		return
	}
	person, err := s.emby.Item(
		ctx,
		credentials(sess),
		personID,
		"Overview,Genres,PrimaryImageAspectRatio",
	)
	if err != nil {
		s.writeUpstreamError(ctx, w, err, "could not load the person")
		return
	}
	if err := s.cache.Set(ctx, key, person, s.cfg.ItemTTL); err != nil {
		s.loggerFor(ctx).Warn("person cache write failed", "error", err)
	}
	w.Header().Set("X-Memby-Cache", "miss")
	writeRaw(w, http.StatusOK, person)
}

// Filmography is kept separate from the biography so life dates can decorate the cast
// row without also loading every cast member's credits.
func (s *Server) handlePersonFilmography(w http.ResponseWriter, r *http.Request, sess store.Session) {
	ctx := r.Context()
	personID := r.PathValue("id")
	if personID == "" {
		writeError(w, http.StatusBadRequest, "person id is required")
		return
	}
	key := cache.UserKey(sess.EmbyUserID, "person-filmography:v1:"+personID)
	if raw, err := s.cache.Get(ctx, key); err == nil {
		w.Header().Set("X-Memby-Cache", "hit")
		writeRaw(w, http.StatusOK, raw)
		return
	}
	result, err := s.emby.Items(ctx, credentials(sess), url.Values{
		"PersonIds":        {personID},
		"IncludeItemTypes": {"Movie,Series"},
		"Recursive":        {"true"},
		"SortBy":           {"ProductionYear,SortName"},
		"SortOrder":        {"Descending"},
		"Limit":            {"60"},
		"Fields":           {"Overview,ProductionYear,PrimaryImageAspectRatio"},
		"EnableImages":     {"true"},
		"EnableImageTypes": {"Primary"},
		"ImageTypeLimit":   {"1"},
		"EnableUserData":   {"true"},
	})
	if err != nil {
		s.writeUpstreamError(ctx, w, err, "could not load the person's filmography")
		return
	}
	items := result.Items
	if items == nil {
		items = []json.RawMessage{}
	}
	body, err := json.Marshal(personFilmographyResponse{Items: items})
	if err != nil {
		writeError(w, http.StatusInternalServerError, "could not encode the filmography")
		return
	}
	if err := s.cache.Set(ctx, key, body, s.cfg.ItemTTL); err != nil {
		s.loggerFor(ctx).Warn("person filmography cache write failed", "error", err)
	}
	w.Header().Set("X-Memby-Cache", "miss")
	writeRaw(w, http.StatusOK, body)
}
