package handler

import (
	"encoding/json"
	"errors"
	"krafttrainer/internal/store"
	"net/http"
	"strconv"
)

// Handler bündelt alle HTTP-Handler und hält eine Referenz auf den Store.
type Handler struct {
	store *store.Store
}

// New erstellt einen neuen Handler.
func New(store *store.Store) *Handler {
	return &Handler{store: store}
}

// RegisterRoutes registriert alle API-Routen am ServeMux.
func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
	// Users (kein X-User-ID Header nötig)
	mux.HandleFunc("GET /api/v1/users", h.handleListUsers)
	mux.HandleFunc("POST /api/v1/users", h.handleCreateUser)
	mux.HandleFunc("DELETE /api/v1/users/{id}", h.handleDeleteUser)

	// Exercises
	mux.HandleFunc("GET /api/v1/exercises", h.handleListExercises)
	mux.HandleFunc("POST /api/v1/exercises", h.handleCreateExercise)
	mux.HandleFunc("PUT /api/v1/exercises/{id}", h.handleUpdateExercise)
	mux.HandleFunc("DELETE /api/v1/exercises/{id}", h.handleDeleteExercise)

	// Training Sets
	mux.HandleFunc("GET /api/v1/sets", h.handleListSets)
	mux.HandleFunc("POST /api/v1/sets", h.handleCreateSet)
	mux.HandleFunc("PUT /api/v1/sets/{id}", h.handleUpdateSet)
	mux.HandleFunc("DELETE /api/v1/sets/{id}", h.handleDeleteSet)

	// Sessions
	mux.HandleFunc("POST /api/v1/sessions", h.handleCreateSession)
	mux.HandleFunc("GET /api/v1/sessions", h.handleListSessions)
	mux.HandleFunc("GET /api/v1/sessions/{id}", h.handleGetSession)
	mux.HandleFunc("PUT /api/v1/sessions/{id}/end", h.handleEndSession)

	// Session Logs
	mux.HandleFunc("POST /api/v1/sessions/{id}/logs", h.handleCreateLog)
	mux.HandleFunc("PUT /api/v1/sessions/{id}/logs/{logId}", h.handleUpdateLog)
	mux.HandleFunc("DELETE /api/v1/sessions/{id}/logs/{logId}", h.handleDeleteLog)

	// Stats
	mux.HandleFunc("GET /api/v1/exercises/{id}/last-log", h.handleGetLastLog)
	mux.HandleFunc("GET /api/v1/exercises/{id}/history", h.handleGetExerciseHistory)
	mux.HandleFunc("GET /api/v1/stats/overview", h.handleGetStatsOverview)

	// Export
	mux.HandleFunc("GET /api/v1/export", h.handleExport)
}

// --- Hilfsfunktionen ---

func writeJSON(w http.ResponseWriter, status int, data any) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	json.NewEncoder(w).Encode(data)
}

func writeError(w http.ResponseWriter, status int, message string) {
	writeJSON(w, status, map[string]string{"error": message})
}

func decodeJSON(r *http.Request, dst any) error {
	dec := json.NewDecoder(r.Body)
	dec.DisallowUnknownFields()
	return dec.Decode(dst)
}

func pathID(r *http.Request, name string) (int64, error) {
	return strconv.ParseInt(r.PathValue(name), 10, 64)
}

func queryInt(r *http.Request, name string, defaultVal int) int {
	v := r.URL.Query().Get(name)
	if v == "" {
		return defaultVal
	}
	n, err := strconv.Atoi(v)
	if err != nil {
		return defaultVal
	}
	return n
}

// userID liest die X-User-ID aus dem Request-Header.
func userID(r *http.Request) (int64, error) {
	v := r.Header.Get("X-User-ID")
	if v == "" {
		return 0, errors.New("X-User-ID Header fehlt")
	}
	id, err := strconv.ParseInt(v, 10, 64)
	if err != nil || id <= 0 {
		return 0, errors.New("ungültige User-ID")
	}
	return id, nil
}
