package sresponse

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

	"github.com/tech/sendico/pkg/api/http/response"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/mservice"
)

type DynamicResponse[T any] struct {
	authResponse `json:",inline"`
	Items        []T
	// FieldName is the JSON key to use for the items.
	FieldName string
}

func (dr DynamicResponse[T]) MarshalJSON() ([]byte, error) {
	// Create a temporary map to hold the keys and values.
	m := map[string]any{
		dr.FieldName:  dr.Items,
		"accessToken": dr.AccessToken,
	}
	return json.Marshal(m)
}

type handler = func(logger mlogger.Logger, data any) http.HandlerFunc

func objectsAuth[T any](logger mlogger.Logger, items []T, accessToken *TokenData, resource mservice.Type, handler handler) http.HandlerFunc {
	resp := &DynamicResponse[T]{
		Items:        items,
		authResponse: authResponse{AccessToken: *accessToken},
		FieldName:    resource,
	}
	return handler(logger, resp)
}

func ObjectsAuth[T any](logger mlogger.Logger, items []T, accessToken *TokenData, resource mservice.Type) http.HandlerFunc {
	return objectsAuth(logger, items, accessToken, resource, response.Ok)
}

func ObjectAuth[T any](logger mlogger.Logger, item *T, accessToken *TokenData, resource mservice.Type) http.HandlerFunc {
	return ObjectsAuth(logger, []T{*item}, accessToken, resource)
}

func ObjectAuthCreated[T any](logger mlogger.Logger, item *T, accessToken *TokenData, resource mservice.Type) http.HandlerFunc {
	return objectsAuth(logger, []T{*item}, accessToken, resource, response.Created)
}
