package tool

import (
	"context"
	"errors"
	"fmt"

	"github.com/ankorstore/yokai-showroom/mcp-demo/internal/domain"
	"github.com/ankorstore/yokai/log"
	"github.com/ankorstore/yokai/trace"
	"github.com/mark3labs/mcp-go/mcp"
	"github.com/mark3labs/mcp-go/server"
)

// CreateGopherTool is the MCP tool to create gophers.
type CreateGopherTool struct {
	service *domain.GopherService
}

// NewCreateGopherTool returns a new CreateGopherTool instance.
func NewCreateGopherTool(service *domain.GopherService) *CreateGopherTool {
	return &CreateGopherTool{
		service: service,
	}
}

// Name returns the CreateGopherTool name.
func (t *CreateGopherTool) Name() string {
	return "create-gopher"
}

// Options returns the CreateGopherTool options.
func (t *CreateGopherTool) Options() []mcp.ToolOption {
	return []mcp.ToolOption{
		mcp.WithDescription("create one new gopher"),
		mcp.WithString(
			"name",
			mcp.Required(),
			mcp.Description("name of the new gopher to create"),
		),
		mcp.WithString(
			"job",
			mcp.Required(),
			mcp.Description("job of the new gopher to create"),
			mcp.Enum("backend", "frontend"),
		),
	}
}

// Handle returns the CreateGopherTool request handler.
func (t *CreateGopherTool) Handle() server.ToolHandlerFunc {
	return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		ctx, span := trace.CtxTracer(ctx).Start(ctx, "CreateGopherTool.Handle")
		defer span.End()

		log.CtxLogger(ctx).Info().Msg("CreateGopherTool.Handle")

		args := request.GetArguments()

		name, ok := args["name"].(string)
		if !ok {
			return nil, errors.New("gopher name must be a string")
		}

		job, ok := args["job"].(string)
		if !ok {
			return nil, errors.New("gopher job must be a string")
		}

		id, err := t.service.Create(ctx, name, job)
		if err != nil {
			return nil, fmt.Errorf("cannot create gopher: %w", err)
		}

		return mcp.NewToolResultText(fmt.Sprintf("gopher was created with id %d", id)), nil
	}
}
