package handlers

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

	"github.com/google/uuid"

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

// GET /api/event-types?category=&jurisdiction=
//
// Returns event_types visible to the caller (firm-wide ∪ own private,
// not archived), optionally filtered by category and/or jurisdiction.
func handleListEventTypes(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	uid, ok := requireUser(w, r)
	if !ok {
		return
	}
	q := r.URL.Query()
	rows, err := dbSvc.eventType.List(r.Context(), uid, services.EventTypeListFilter{
		Category:     q.Get("category"),
		Jurisdiction: q.Get("jurisdiction"),
	})
	if err != nil {
		writeServiceError(w, err)
		return
	}
	writeJSON(w, http.StatusOK, rows)
}

// GET /api/event-types/suggest?q=foo — surfaces firm-wide rows whose
// label_de or label_en matches `q` (case-insensitive substring) so the
// add-modal can warn "Existiert vermutlich schon: …".
func handleSuggestEventTypes(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	uid, ok := requireUser(w, r)
	if !ok {
		return
	}
	rows, err := dbSvc.eventType.SuggestSimilar(r.Context(), uid, r.URL.Query().Get("q"))
	if err != nil {
		writeServiceError(w, err)
		return
	}
	writeJSON(w, http.StatusOK, rows)
}

// POST /api/event-types
//
// Creates a private (default) or firm-wide (is_firm_wide=true) type for
// the caller. Any authenticated user may set is_firm_wide=true (per m's
// Q6 call); admins moderate via PATCH archive=true after the fact.
func handleCreateEventType(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	uid, ok := requireUser(w, r)
	if !ok {
		return
	}
	var input services.CreateEventTypeInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON"})
		return
	}
	row, err := dbSvc.eventType.Create(r.Context(), uid, input)
	if err != nil {
		writeServiceError(w, err)
		return
	}
	writeJSON(w, http.StatusCreated, row)
}

// PATCH /api/event-types/{id}
//
// Edits or archives an event_type. Authorization: author of the row,
// or global_admin if the row is firm-wide. Soft-delete only — set
// {"archive": true} to hide the type from pickers without breaking
// any deadline that already references it.
func handleUpdateEventType(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	uid, ok := requireUser(w, r)
	if !ok {
		return
	}
	id, err := uuid.Parse(r.PathValue("id"))
	if err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
		return
	}
	var input services.UpdateEventTypeInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON"})
		return
	}
	row, err := dbSvc.eventType.Update(r.Context(), uid, id, input)
	if err != nil {
		writeServiceError(w, err)
		return
	}
	writeJSON(w, http.StatusOK, row)
}
