package anthropic

import (
	"cursor-api-proxy/internal/openai"
	"encoding/json"
	"fmt"
	"strings"
)

type MessageParam struct {
	Role    string      `json:"role"`
	Content interface{} `json:"content"`
}

type MessagesRequest struct {
	Model     string        `json:"model"`
	MaxTokens int           `json:"max_tokens"`
	Messages  []MessageParam `json:"messages"`
	System    interface{}   `json:"system"`
	Stream    bool          `json:"stream"`
	Tools     []interface{} `json:"tools"`
}

func systemToText(system interface{}) string {
	if system == nil {
		return ""
	}
	switch v := system.(type) {
	case string:
		return strings.TrimSpace(v)
	case []interface{}:
		var parts []string
		for _, p := range v {
			if m, ok := p.(map[string]interface{}); ok {
				if m["type"] == "text" {
					if t, ok := m["text"].(string); ok {
						parts = append(parts, t)
					}
				}
			}
		}
		return strings.Join(parts, "\n")
	}
	return ""
}

func anthropicBlockToText(p interface{}) string {
	if p == nil {
		return ""
	}
	switch v := p.(type) {
	case string:
		return v
	case map[string]interface{}:
		typ, _ := v["type"].(string)
		switch typ {
		case "text":
			if t, ok := v["text"].(string); ok {
				return t
			}
		case "image":
			if src, ok := v["source"].(map[string]interface{}); ok {
				srcType, _ := src["type"].(string)
				switch srcType {
				case "base64":
					mt, _ := src["media_type"].(string)
					if mt == "" {
						mt = "image"
					}
					return "[Image: base64 " + mt + "]"
				case "url":
					url, _ := src["url"].(string)
					return "[Image: " + url + "]"
				}
			}
			return "[Image]"
		case "document":
			title, _ := v["title"].(string)
			if title == "" {
				if src, ok := v["source"].(map[string]interface{}); ok {
					title, _ = src["url"].(string)
				}
			}
			if title != "" {
				return "[Document: " + title + "]"
			}
			return "[Document]"
		case "tool_use":
			name, _ := v["name"].(string)
			id, _ := v["id"].(string)
			input := v["input"]
			inputJSON, _ := json.Marshal(input)
			if inputJSON == nil {
				inputJSON = []byte("{}")
			}
			tag := fmt.Sprintf("<tool_call>\n{\"name\": \"%s\", \"arguments\": %s}\n</tool_call>", name, string(inputJSON))
			if id != "" {
				tag = fmt.Sprintf("[tool_use_id=%s] ", id) + tag
			}
			return tag
		case "tool_result":
			toolUseID, _ := v["tool_use_id"].(string)
			content := v["content"]
			var contentText string
			switch c := content.(type) {
			case string:
				contentText = c
			case []interface{}:
				var parts []string
				for _, block := range c {
					if bm, ok := block.(map[string]interface{}); ok {
						if bm["type"] == "text" {
							if t, ok := bm["text"].(string); ok {
								parts = append(parts, t)
							}
						}
					}
				}
				contentText = strings.Join(parts, "\n")
			}
			label := "Tool result"
			if toolUseID != "" {
				label += " [id=" + toolUseID + "]"
			}
			return label + ": " + contentText
		}
	}
	return ""
}

func anthropicContentToText(content interface{}) string {
	switch v := content.(type) {
	case string:
		return v
	case []interface{}:
		var parts []string
		for _, p := range v {
			if t := anthropicBlockToText(p); t != "" {
				parts = append(parts, t)
			}
		}
		return strings.Join(parts, " ")
	}
	return ""
}

func BuildPromptFromAnthropicMessages(messages []MessageParam, system interface{}) string {
	var oaiMessages []interface{}

	systemText := systemToText(system)
	if systemText != "" {
		oaiMessages = append(oaiMessages, map[string]interface{}{
			"role":    "system",
			"content": systemText,
		})
	}

	for _, m := range messages {
		text := anthropicContentToText(m.Content)
		if text == "" {
			continue
		}
		role := m.Role
		if role != "user" && role != "assistant" {
			role = "user"
		}
		oaiMessages = append(oaiMessages, map[string]interface{}{
			"role":    role,
			"content": text,
		})
	}

	return openai.BuildPromptFromMessages(oaiMessages)
}
