package llm_service

import (
	"ai_scheduler/internal/config"
	"ai_scheduler/internal/entitys"
	"ai_scheduler/internal/pkg"
	"ai_scheduler/internal/pkg/utils_vllm"
	"context"
	"encoding/base64"
	"errors"
	"fmt"
	"strings"

	"github.com/cloudwego/eino/schema"
	"github.com/ollama/ollama/api"
)

type VllmService struct {
	client *utils_vllm.Client
	config *config.Config
}

func NewVllmService(
	client *utils_vllm.Client,
	config *config.Config,
) *VllmService {
	return &VllmService{
		client: client,
		config: config,
	}
}

func (s *VllmService) IntentRecognize(ctx context.Context, req *entitys.ToolSelect) (msg string, err error) {
	msgs := s.convertMessages(req.Prompt)
	tools := s.convertTools(req.Tools)

	resp, err := s.client.ToolSelect(ctx, msgs, tools)
	if err != nil {
		return
	}

	if resp.Content == "" {
		if len(resp.ToolCalls) > 0 {
			call := resp.ToolCalls[0]
			var matchFromTools = &entitys.Match{
				Confidence: 1,
				Index:      call.Function.Name,
				Parameters: call.Function.Arguments,
				IsMatch:    true,
			}
			msg = pkg.JsonStringIgonErr(matchFromTools)
		} else {
			err = errors.New("不太明白你想表达的意思呢，可以在仔细描述一下您所需要的内容吗，感谢感谢")
			return
		}
	} else {
		msg = resp.Content
	}
	return
}

func (s *VllmService) convertMessages(prompts []api.Message) []*schema.Message {
	msgs := make([]*schema.Message, 0, len(prompts))
	for _, p := range prompts {
		msg := &schema.Message{
			Role:    schema.RoleType(p.Role),
			Content: p.Content,
		}

		// 这里实际应该不会走进来
		if len(p.Images) > 0 {
			parts := []schema.MessageInputPart{
				{Type: schema.ChatMessagePartTypeText, Text: p.Content},
			}
			for _, imgData := range p.Images {
				b64 := base64.StdEncoding.EncodeToString(imgData)
				mimeType := "image/jpeg"
				parts = append(parts, schema.MessageInputPart{
					Type: schema.ChatMessagePartTypeImageURL,
					Image: &schema.MessageInputImage{
						MessagePartCommon: schema.MessagePartCommon{
							MIMEType:   mimeType,
							Base64Data: &b64,
						},
					},
				})
			}
			msg.UserInputMultiContent = parts
		}
		msgs = append(msgs, msg)
	}
	return msgs
}

func (s *VllmService) convertTools(tasks []entitys.RegistrationTask) []*schema.ToolInfo {
	tools := make([]*schema.ToolInfo, 0, len(tasks))
	for _, task := range tasks {
		params := make(map[string]*schema.ParameterInfo)
		for k, v := range task.TaskConfigDetail.Param.Properties {
			dt := schema.String

			// Handle v.Type dynamically to support both string and []string (compiler suggests []string)
			// Using fmt.Sprint handles both cases safely without knowing exact type structure
			typeStr := fmt.Sprintf("%v", v.Type)
			typeStr = strings.Trim(typeStr, "[]") // normalize "[string]" -> "string"

			switch typeStr {
			case "string":
				dt = schema.String
			case "integer", "int":
				dt = schema.Integer
			case "number", "float":
				dt = schema.Number
			case "boolean", "bool":
				dt = schema.Boolean
			case "object":
				dt = schema.Object
			case "array":
				dt = schema.Array
			}

			required := false
			for _, r := range task.TaskConfigDetail.Param.Required {
				if r == k {
					required = true
					break
				}
			}

			desc := v.Description
			if len(v.Enum) > 0 {
				var enumStrs []string
				for _, e := range v.Enum {
					enumStrs = append(enumStrs, fmt.Sprintf("%v", e))
				}
				desc += " Enum: " + strings.Join(enumStrs, ", ")
			}

			params[k] = &schema.ParameterInfo{
				Type:     dt,
				Desc:     desc,
				Required: required,
			}
		}

		tools = append(tools, &schema.ToolInfo{
			Name:        task.Name,
			Desc:        task.Desc,
			ParamsOneOf: schema.NewParamsOneOfByParams(params),
		})
	}
	return tools
}
