package main

import (
	"context"
	"fmt"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func evalCreateMessageHandler(_ context.Context, _ *mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) {
	return &mcp.CreateMessageResult{
		Content: &mcp.TextContent{Text: "## Mock Analysis\n\nThis analysis was generated by the eval_mcp_surfaces sampling handler."},
		Model:   "eval-mcp-surfaces-sampling-mock",
		Role:    "assistant",
	}, nil
}

// evalElicitationHandler auto-accepts evaluator elicitation requests with deterministic fixture values.
func evalElicitationHandler(_ context.Context, req *mcp.ElicitRequest) (*mcp.ElicitResult, error) {
	content := make(map[string]any)
	schema, ok := req.Params.RequestedSchema.(map[string]any)
	if ok {
		if props, propsOK := schema["properties"].(map[string]any); propsOK {
			for key, val := range props {
				prop, propOK := val.(map[string]any)
				if !propOK {
					continue
				}
				switch key {
				case "confirmed":
					content[key] = true
				case "selection":
					content[key] = evalElicitationSelection(prop)
				default:
					content[key] = evalElicitationSchemaValue(key, prop)
				}
			}
		}
	}
	return &mcp.ElicitResult{Action: "accept", Content: content}, nil
}

// evalElicitationSchemaValue derives eval elicitation schema value from tool schema metadata.
func evalElicitationSchemaValue(fieldName string, prop map[string]any) any {
	if enumVals, ok := prop["enum"].([]any); ok && len(enumVals) > 0 {
		return enumVals[0]
	}
	switch firstJSONSchemaType(prop["type"]) {
	case "integer":
		return 0
	case "number":
		return 0.0
	case "boolean":
		return false
	case "array":
		return []any{}
	case "object":
		return evalElicitationObjectValue(prop)
	default:
		return evalElicitationTextValue(fieldName)
	}
}

// evalElicitationObjectValue builds nested sample content for object elicitation schemas.
func evalElicitationObjectValue(prop map[string]any) map[string]any {
	content := map[string]any{}
	properties, ok := prop["properties"].(map[string]any)
	if !ok {
		return content
	}
	for key, value := range properties {
		child, childOK := value.(map[string]any)
		if !childOK {
			continue
		}
		content[key] = evalElicitationSchemaValue(key, child)
	}
	return content
}

// firstJSONSchemaType returns the first JSON schema type value that is set.
func firstJSONSchemaType(value any) string {
	switch typed := value.(type) {
	case string:
		return typed
	case []any:
		for _, item := range typed {
			if text, ok := item.(string); ok && text != "null" {
				return text
			}
		}
	}
	return "string"
}

// evalElicitationSelection returns the first enum value from an elicitation select field.
func evalElicitationSelection(prop map[string]any) string {
	if enumVals, ok := prop["enum"].([]any); ok && len(enumVals) > 0 {
		if selection, selectionOK := enumVals[0].(string); selectionOK && selection != "" {
			return selection
		}
	}
	return "default"
}

// evalElicitationTextValue returns stable values that match the Docker live fixture.
func evalElicitationTextValue(fieldName string) string {
	switch fieldName {
	case "title":
		return "Evaluation elicitation test"
	case "description":
		return "Created by eval_mcp_surfaces elicitation handler"
	case "name":
		return fmt.Sprintf("eval-elicit-resource-%s", liveUniqueSuffix())
	case "source_branch":
		return liveFixtureFeatureRef
	case "target_branch", "default_branch":
		return liveFixtureDefaultRef
	case "tag_name":
		return evalElicitationReleaseTagName()
	case "labels":
		return "evaluation"
	default:
		return "eval-elicit-" + fieldName
	}
}

// setEvalElicitationReleaseTag updates the tag returned by the evaluator elicitation handler.
func setEvalElicitationReleaseTag(tagName string) {
	evalElicitationReleaseTag.Store(tagName)
}

// evalElicitationReleaseTagName returns the currently prepared release tag.
func evalElicitationReleaseTagName() string {
	if tagName, ok := evalElicitationReleaseTag.Load().(string); ok && tagName != "" {
		return tagName
	}
	return liveFixtureElicitationTag
}

// convertTools resolves convert tools for evaluator execution.
