package handlers

// HTTP handlers for paliad.project_event_choices (t-paliad-265 / m/paliad#96).
//
// Three endpoints:
//   GET    /api/projects/{id}/event-choices            → list
//   PUT    /api/projects/{id}/event-choices            → upsert one
//   DELETE /api/projects/{id}/event-choices/{submission_code}/{choice_kind}
//
// All three gated by visibility on the project (paliad.can_see_project)
// via EventChoiceService.

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

	"github.com/google/uuid"

	"mgit.msbls.de/m/paliad/internal/services"
)

// GET /api/projects/{id}/event-choices
func handleListProjectEventChoices(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	uid, ok := requireUser(w, r)
	if !ok {
		return
	}
	if dbSvc.eventChoice == nil {
		writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "event-choice service not configured"})
		return
	}
	projectID, err := uuid.Parse(r.PathValue("id"))
	if err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid project id"})
		return
	}
	rows, err := dbSvc.eventChoice.ListForProject(r.Context(), uid, projectID)
	if err != nil {
		writeServiceError(w, err)
		return
	}
	writeJSON(w, http.StatusOK, rows)
}

// PUT /api/projects/{id}/event-choices — upsert one row.
func handlePutProjectEventChoice(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	uid, ok := requireUser(w, r)
	if !ok {
		return
	}
	if dbSvc.eventChoice == nil {
		writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "event-choice service not configured"})
		return
	}
	projectID, err := uuid.Parse(r.PathValue("id"))
	if err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid project id"})
		return
	}
	var input services.UpsertEventChoiceInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON body"})
		return
	}
	row, err := dbSvc.eventChoice.Upsert(r.Context(), uid, projectID, input)
	if err != nil {
		if errors.Is(err, services.ErrInvalidInput) {
			writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
			return
		}
		writeServiceError(w, err)
		return
	}
	writeJSON(w, http.StatusOK, row)
}

// DELETE /api/projects/{id}/event-choices/{submission_code}/{choice_kind}
func handleDeleteProjectEventChoice(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	uid, ok := requireUser(w, r)
	if !ok {
		return
	}
	if dbSvc.eventChoice == nil {
		writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "event-choice service not configured"})
		return
	}
	projectID, err := uuid.Parse(r.PathValue("id"))
	if err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid project id"})
		return
	}
	submissionCode := r.PathValue("submission_code")
	choiceKind := r.PathValue("choice_kind")
	if err := dbSvc.eventChoice.Delete(r.Context(), uid, projectID, submissionCode, choiceKind); err != nil {
		if errors.Is(err, services.ErrInvalidInput) {
			writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
			return
		}
		writeServiceError(w, err)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
