package cmd

import (
	"context"
	"slices"
	"strings"

	"git.bissendorf.co/bissendorf/unifood/m/v2/core/handler/meals"
	"git.bissendorf.co/bissendorf/unifood/m/v2/core/handler/universities"
	"git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces"
	"git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces/params"
	"git.bissendorf.co/bissendorf/unifood/m/v2/core/services/stwhbclient"
	"git.bissendorf.co/bissendorf/unifood/m/v2/model/external/stwbremen"
	"git.bissendorf.co/bissendorf/unifood/m/v2/model/resources"
	"git.bissendorf.co/bissendorf/unifood/m/v2/util"
)

var availableResources = []interfaces.ResourceCommand[any]{
	{
		Name:        "resources",
		Aliases:     []string{"resource"},
		Description: "A meta resource representing all other object kinds of this CLI.",
		Verbs:       []interfaces.Verb{interfaces.VerbGet},
		Handler:     &registeredResourcesHandler{},
	},
	{
		Name:        "meals",
		Aliases:     []string{"meal", "m"},
		Description: "A meal represents a cooked combination of ingredients that can be bought and consumed.",
		Verbs:       []interfaces.Verb{interfaces.VerbGet},
		Handler: &meals.MealsHandler{
			QueryClient: stwhbclient.New[[]stwbremen.Meal](),
		},
	},
	{
		Name:        "universities",
		Aliases:     []string{"university", "unis", "uni", "u"},
		Description: "A facility that is hosting one or multiple restaurants.",
		Verbs:       []interfaces.Verb{interfaces.VerbGet},
		Handler: &universities.UniversityHandler{
			QueryClient: stwhbclient.New[stwbremen.RestaurantList](),
		},
	},
	{
		Name:        "restaurants",
		Aliases:     []string{"restaurant", "r"},
		Description: "A place to eat meals",
		Verbs:       []interfaces.Verb{interfaces.VerbGet},
		Handler: &universities.RestaurantHandler{
			QueryClient:           stwhbclient.New[stwbremen.RestaurantList](),
			QueryClientRestaurant: stwhbclient.New[stwbremen.Restaurant](),
		},
	},
}

type registeredResourcesHandler struct{}

func (h *registeredResourcesHandler) Get(ctx context.Context, name string, params params.Container) (*interfaces.ResourceList, error) {
	lowerName := strings.ToLower(name)
	list := util.Select(availableResources, func(i *interfaces.ResourceCommand[any]) bool {
		return name == "" || i.Name == lowerName
	})

	slices.SortFunc(list, func(a, b interfaces.ResourceCommand[any]) int {
		return strings.Compare(a.Name, b.Name)
	})

	return &interfaces.ResourceList{
		ItemKind: resources.ResourceResource,
		Items: util.Transform(list, func(i *interfaces.ResourceCommand[any]) interfaces.Resource {
			return &resources.Resource{
				ResourceName: i.Name,
				Aliases:      i.Aliases,
				Description:  i.Description,
			}
		}),
	}, nil
}

func (h *registeredResourcesHandler) GetParametersForVerb(verb interfaces.Verb) []params.Registration {
	return []params.Registration{}
}
