// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: LicenseRef-MutuaL-1.2

package mcp

import (
	"context"

	"git.secluded.site/cooked-mcp/internal/cooked"
)

const (
	testRecipeID        = "38f161dd-a514-4d5a-a924-0227695d9151"
	testRecipeID2       = "38f161dd-a514-4d5a-a924-0227695d9152"
	testOtherRecipeID   = "8263f928-1111-4222-8333-123456789abc"
	testDraftID         = "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee"
	testProductGroupID  = "11111111-2222-4333-8444-555555555555"
	testProductGroupID2 = "66666666-7777-4888-9999-aaaaaaaaaaaa"
	testProductGroupID3 = "77777777-8888-4999-aaaa-bbbbbbbbbbbb"
	testProductGroupID4 = "88888888-9999-4aaa-bbbb-cccccccccccc"
)

type fakeBackend struct {
	shoppingList                     cooked.ShoppingList
	recipes                          []cooked.RecipeCard
	recipesByPage                    map[int][]cooked.RecipeCard
	searchRecipes                    []cooked.RecipeCard
	recipeMetadata                   cooked.RecipeMetadata
	recipeContent                    cooked.RecipeContent
	preview                          cooked.RecipeTextPreview
	importRecipeURLResult            cooked.RecipeURLImport
	saveRecipeID                     string
	draftSaveRecipeID                string
	page                             int
	limit                            int
	searchQuery                      string
	searchPage                       int
	metadataRecipeID                 string
	contentRecipeID                  string
	previewTitle                     string
	previewText                      string
	importURL                        string
	saveTitle                        string
	saveMarkdown                     string
	savePortions                     float64
	draftSaveID                      string
	draftSaveMarkdown                string
	draftSavePortions                float64
	updateRecipeID                   string
	updateMarkdown                   string
	updatePortions                   float64
	deleteRecipeID                   string
	addShoppingListResult            cooked.AddShoppingListResult
	addIngredients                   string
	addRecipeID                      string
	removeProductGroupIDs            []string
	replaceSelectionProductGroupIDs  []string
	updateShoppingListProductGroupID string
	updateShoppingListProductGroup   cooked.ShoppingListProductGroupUpdate
	metadataCalls                    int
	listRecipeCalls                  int
	readShoppingListCalls            int
	contentCalls                     int
	previewCalls                     int
	importRecipeURLCalls             int
	saveCalls                        int
	draftSaveCalls                   int
	updateCalls                      int
	deleteCalls                      int
	clearShoppingListCalls           int
	addShoppingListCalls             int
	removeShoppingListCalls          int
	replaceSelectionCalls            int
	updateShoppingListCalls          int
}

func (f *fakeBackend) ReadShoppingList(context.Context) (cooked.ShoppingList, error) {
	f.readShoppingListCalls++

	return f.shoppingList, nil
}

func (f *fakeBackend) ListRecipes(_ context.Context, page, limit int) ([]cooked.RecipeCard, error) {
	f.page = page
	f.limit = limit
	f.listRecipeCalls++
	if f.recipesByPage != nil {
		return f.recipesByPage[page], nil
	}

	return f.recipes, nil
}

func (f *fakeBackend) SearchRecipes(_ context.Context, query string, page int) ([]cooked.RecipeCard, error) {
	f.searchQuery = query
	f.searchPage = page

	return f.searchRecipes, nil
}

func (f *fakeBackend) ReadRecipeMetadata(_ context.Context, recipeID string) (cooked.RecipeMetadata, error) {
	f.metadataRecipeID = recipeID
	f.metadataCalls++

	return f.recipeMetadata, nil
}

func (f *fakeBackend) ReadRecipeContent(_ context.Context, recipeID string) (cooked.RecipeContent, error) {
	f.contentRecipeID = recipeID
	f.contentCalls++

	return f.recipeContent, nil
}

func (f *fakeBackend) PreviewRecipeText(_ context.Context, title, text string) (cooked.RecipeTextPreview, error) {
	f.previewTitle = title
	f.previewText = text
	f.previewCalls++

	return f.preview, nil
}

func (f *fakeBackend) SavePreparedRecipe(_ context.Context, title, markdown string, portions float64) (string, error) {
	f.saveTitle = title
	f.saveMarkdown = markdown
	f.savePortions = portions
	f.saveCalls++
	if f.saveRecipeID != "" {
		return f.saveRecipeID, nil
	}

	return testRecipeID, nil
}

func (f *fakeBackend) SaveRecipeDraft(_ context.Context, draftID, markdown string, portions float64) (string, error) {
	f.draftSaveID = draftID
	f.draftSaveMarkdown = markdown
	f.draftSavePortions = portions
	f.draftSaveCalls++
	if f.draftSaveRecipeID != "" {
		return f.draftSaveRecipeID, nil
	}

	return testRecipeID, nil
}

func (f *fakeBackend) UpdateRecipeContent(_ context.Context, recipeID, markdown string, portions float64) error {
	f.updateRecipeID = recipeID
	f.updateMarkdown = markdown
	f.updatePortions = portions
	f.updateCalls++

	return nil
}

func (f *fakeBackend) ImportRecipeURL(_ context.Context, recipeURL string) (cooked.RecipeURLImport, error) {
	f.importURL = recipeURL
	f.importRecipeURLCalls++

	return f.importRecipeURLResult, nil
}

func (f *fakeBackend) DeleteRecipe(_ context.Context, recipeID string) error {
	f.deleteRecipeID = recipeID
	f.deleteCalls++

	return nil
}

func (f *fakeBackend) ClearShoppingList(context.Context) error {
	f.clearShoppingListCalls++

	return nil
}

func (f *fakeBackend) AddShoppingListIngredients(
	_ context.Context,
	ingredients, recipeID string,
) (cooked.AddShoppingListResult, error) {
	f.addIngredients = ingredients
	f.addRecipeID = recipeID
	f.addShoppingListCalls++

	return f.addShoppingListResult, nil
}

func (f *fakeBackend) RemoveShoppingListProductGroups(_ context.Context, ids []string) error {
	f.removeProductGroupIDs = ids
	f.removeShoppingListCalls++

	return nil
}

func (f *fakeBackend) ReplaceShoppingListSelection(_ context.Context, ids []string) error {
	f.replaceSelectionProductGroupIDs = ids
	f.replaceSelectionCalls++

	return nil
}

func (f *fakeBackend) UpdateShoppingListProductGroup(
	_ context.Context,
	productGroupID string,
	update cooked.ShoppingListProductGroupUpdate,
) error {
	f.updateShoppingListProductGroupID = productGroupID
	f.updateShoppingListProductGroup = update
	f.updateShoppingListCalls++

	return nil
}
