package handlers

import (
	"errors"
	"net/http"

	"github.com/go-chi/chi/v5"

	"git.threesix.ai/jordan/slack5-1770529463/pkg/app"
	"git.threesix.ai/jordan/slack5-1770529463/pkg/httperror"
	"git.threesix.ai/jordan/slack5-1770529463/pkg/httpresponse"
	"git.threesix.ai/jordan/slack5-1770529463/pkg/logging"
	"git.threesix.ai/jordan/slack5-1770529463/services/preferences-api/internal/domain"
	"git.threesix.ai/jordan/slack5-1770529463/services/preferences-api/internal/service"
)

// Preference handles HTTP requests for user preferences.
type Preference struct {
	svc    *service.PreferenceService
	logger *logging.Logger
}

// NewPreference creates a new Preference handler with injected dependencies.
func NewPreference(svc *service.PreferenceService, logger *logging.Logger) *Preference {
	return &Preference{
		svc:    svc,
		logger: logger.WithComponent("PreferenceHandler"),
	}
}

// UpdatePreferencesRequest is the request body for updating preferences.
type UpdatePreferencesRequest struct {
	Preferences map[string]any `json:"preferences"`
}

// PreferencesResponse is the response for preference endpoints.
type PreferencesResponse struct {
	UserID      string         `json:"user_id"`
	Preferences map[string]any `json:"preferences"`
}

// GetPreferences returns all preferences for a user.
func (h *Preference) GetPreferences(w http.ResponseWriter, r *http.Request) error {
	userID := chi.URLParam(r, "user_id")

	result, err := h.svc.GetPreferences(r.Context(), userID)
	if err != nil {
		return mapPreferenceError(err)
	}

	httpresponse.OK(w, r, PreferencesResponse{
		UserID:      result.UserID,
		Preferences: result.Preferences,
	})
	return nil
}

// UpdatePreferences creates or updates preferences for a user.
func (h *Preference) UpdatePreferences(w http.ResponseWriter, r *http.Request) error {
	userID := chi.URLParam(r, "user_id")

	var req UpdatePreferencesRequest
	if err := app.Bind(r, &req); err != nil {
		return err
	}

	result, err := h.svc.UpdatePreferences(r.Context(), userID, req.Preferences)
	if err != nil {
		return mapPreferenceError(err)
	}

	httpresponse.OK(w, r, PreferencesResponse{
		UserID:      result.UserID,
		Preferences: result.Preferences,
	})
	return nil
}

// mapPreferenceError converts domain errors to HTTP errors.
func mapPreferenceError(err error) error {
	switch {
	case errors.Is(err, domain.ErrInvalidUserID):
		return httperror.BadRequest("invalid user_id format: must be a valid UUID")
	case errors.Is(err, domain.ErrUnknownPreferenceKey):
		return httperror.BadRequest(err.Error())
	case errors.Is(err, domain.ErrInvalidPreferenceValue):
		return httperror.BadRequest(err.Error())
	default:
		return err
	}
}
